Trending-topic targeting, and 90 days free with it - #248
Merged
Merged
Conversation
ThreatCrush Security Scan39 finding(s) HIGH/CRITICAL: 2 | MEDIUM: 28 | LOW: 9
Snippets are redacted; ThreatCrush never prints matched credential material. |
Targeting on what chovy.com's SameBrain says founders are trying to build this week, and the 90 days free that comes with turning it on. Two halves have to agree before a campaign is preferred: its own subject has to be trending AND the page being filled has to be about that subject. Either half alone is how an ad network ends up putting a crypto ad on a recipe blog — one is "this is in the news", the other is ordinary contextual targeting. The page's subject is not new work: the autoblog already keeps a hand-checked subject list per site (lx_site.master_keywords) and that is what is read. It is a preference, not a rule. A match carries four times its own bid weight into the same bid-weighted lottery, so it wins more fills and every other eligible campaign still rotates — the auction's hard requirement. The promo separates two questions that look like one. A campaign inside its ninety days COMPETES for real placement (that is what premium delivery means; parked in the backfill pool it would never serve at all next to a paying advertiser) and BOOKS as tier='free', because nothing is charged. So no spend and no publisher earnings are written for a payment that is not happening — which matters most here, where one account owns both sides of nearly every fill and a paid booking would read as revenue on the ROI dashboard. It is not revenue. It is a discount we gave ourselves. Billing at zero is settled in resolveClick rather than inside ad_charge_click: that function is the hottest SQL in the product and its migrations are applied by hand, so teaching it about promos would put a new failure mode in front of every click on the network. Degrading is the design everywhere it touches. A trend list older than 36 hours stops steering delivery instead of targeting last week forever; a failed pull leaves the stored list; a missing table or column — the migration is applied by hand, so a deploy can lead it — reads as "nobody is trending", which is exactly how serving behaved yesterday. On a network where nobody has opted in this costs one cached query a minute and nothing per fill. $0.02 CPC is stated once, in lib/ads/pricing.ts, and quoted from there by the dashboard, the CLI and the promo row. Known gap recorded there: it is smaller than one credit (5c), and nothing bills a fraction of a credit today, so after a promo ends a trending campaign bills at its ordinary bid until sub-credit metering exists. The migration is added, not applied — apply it one file at a time. SAMEBRAIN_URL and SAMEBRAIN_SECRET go in the vault and on the deployment, never in a committed .env file. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QuUkTrofSjQ15j79mRuy4f
ralyodio
marked this pull request as ready for review
September 12, 2026 11:31
ralyodio
force-pushed
the
feat/samebrain-trend-targeting
branch
from
September 12, 2026 11:31
9eabba0 to
75aa221
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Run ads where the subject is what people are asking about right now, and give an advertiser who turns it on ninety days during which every click is billed at $0.00.
The signals come from SameBrain on chovy.com — what founders are asking to build this week. That endpoint did not exist; it is built in profullstack/chovy-ai#9 and this branch is the puller.
Targeting
Two halves have to agree before a campaign is preferred: its own subject has to be trending and the page being filled has to be about that subject. Either half alone is how an ad network ends up putting a crypto ad on a recipe blog — one is "this is in the news", the other is ordinary contextual targeting.
The page's subject is not new work: the autoblog already keeps a hand-checked subject list per site (
lx_site.master_keywords), and that, the niche and the slot's niche are what get read.It is a preference, not a rule. A match carries 4× its own bid weight into the same bid-weighted lottery, so it wins more fills and every other eligible campaign still rotates — the auction's hard requirement, tested.
The promo, and why it books as free
A campaign inside its ninety days competes for real placement (that is what premium delivery means; parked in the backfill pool it would never serve at all next to a paying advertiser) and books as
tier='free', because nothing is charged.So no spend and no publisher earnings are written for a payment that is not happening. That matters most here, where one account owns both sides of nearly every fill: a paid booking would read as revenue on the ROI dashboard. It is not revenue — it is a discount we gave ourselves.
Billing at zero is settled in
resolveClick, not insidead_charge_click: that function is the hottest SQL in the product and its migrations are applied by hand, so teaching it about promos would put a new failure mode in front of every click on the network.Degrading
Surfaces
GET /api/ads/v1/trends(bearer token) ·POST /api/cron/ad-trends(cron secret, hourly)POST /api/ads/v1/campaigns { trending_topics, topics },PATCHthe samecrawlproof ads trends,ads create --trending --topics=,ads trending <ref> on|off; promo days left onads showandads list$0.02
Stated once in
lib/ads/pricing.tsand quoted from there by the dashboard, the CLI and the promo row. Known gap, recorded in that file: $0.02 is smaller than one credit (5¢) and nothing bills a fraction of a credit today, so after a promo ends a trending campaign bills at its ordinary bid until sub-credit metering exists.Migration
supabase/migrations/20260911120000_ad_trend_targeting.sqlis added, not applied. Apply it one file at a time via the Supabase MCP. Nothing in it backfills a row that serving reads, so before or after the deploy are both safe.Secrets to set
SAMEBRAIN_URLandSAMEBRAIN_SECRETon the Railway service and in the vault (crawlproof-com--prod), the secret matching chovy.com's.Tests
vitest run— 2174 passed, 7 skipped, 168 files, 29 of them new (topic matching, the promo window, billing at zero, and a serving contract test for delivery preference and promo tiering).tsc --noEmitclean.npm run lintfails onmastertoo: it runsnext lint, which Next 16 removed, and the repo has no eslint config or binary.🤖 Generated with Claude Code
https://claude.ai/code/session_01QuUkTrofSjQ15j79mRuy4f