You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 782cca8
Browse filesBrowse the repository at this point in the historyBrowse files
Ads: autobid by default, paper-money auction, bid history (#253)
Every campaign on the network is self-deal, so serveAd demoted every fill to
the free tier and the free tier weighted everything at 1: nobody bid, and the
auction, pacing and charge path had never run end to end with real numbers.
- `autobid` on ad_campaigns, default true for every row. A pure pacing
controller (lib/ads/autobid.ts) recomputes each bid hourly from the worker:
behind daily pace raises it, ahead lowers it, capped by what the daily
budget covers, held when already well above the market. The bid field is
gone from the create form; the edit form shows an Autobid switch and the
current bid, with a typed bid only when the switch is off.
- The free tier is a paper auction: the same bid-weighted lottery, weighted by
the paper bid and gated by a paper daily budget. Every free-tier click
records what it would have cost (ad_clicks.paper_cents, campaign paper
counters) through a new ad_paper_charge RPC that refuses any billed click.
No credit balance is ever debited; the paid tier is untouched.
- ad_bids logs every decision with its signals. The campaign page charts bid
against impressions, clicks and tracker-attributed visits, with the last
decisions and their reasons underneath. GET /api/ads/v1/campaigns/[id]
carries the same under stats.bid; PATCH takes `autobid`; a bare bid_credits
turns autobid off. CLI: `crawlproof ads bid <ref> auto|<credits>`.
Migration 20260913120000_ad_autobid.sql is applied to prod (ref
ywcizjsgrcmhgyplldac) and every function was exercised in a rolled-back
transaction. The worker seeds every campaign's first bid at boot.
Claude-Session: https://claude.ai/code/session_01PDJmt1CPi1fAkpD4FXRSHu
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
? `Currently ${campaign.bidCredits} credits ($${((campaign.bidCredits*5)/100).toFixed(2)}). Set every hour from your daily budget and delivery: raised when behind pace, lowered when ahead.`
162
+
: "Off. The bid below is kept until you turn autobid back on."}
Copy file name to clipboardExpand all lines: app/(marketing)/ads/page.tsx
+2-2Lines changed: 2 additions & 2 deletions
Original file line number
Diff line number
Diff line change
@@ -112,8 +112,8 @@ export default async function AdsMarketingPage() {
112
112
113
113
<divclassName="mt-6 grid gap-4 sm:grid-cols-2">
114
114
<Card
115
-
title="You are not bidding against a wall"
116
-
body="Placement is a bid-weighted lottery, not winner-takes-all. A higher bid wins more often, but it never corners the inventory — every live campaign keeps serving, so a modest budget still gets delivery instead of silence."
115
+
title="You set a budget. The bid sets itself."
116
+
body="Placement is a bid-weighted lottery, not winner-takes-all, and the bid is automatic: a pacing controller raises it when a campaign is behind its daily budget and lowers it when ahead, capped by what the budget can cover. Every live campaign keeps serving, so a modest budget still gets delivery instead of silence, and the campaign page shows every bid it made beside the clicks it got."
0 commit comments