ads: refuse a click whose impression is too old for its audience - #264
Merged
Merged
Conversation
A distributed headless-browser crawler fetches rssamplifier.com's feed documents with a plain Chrome user agent, harvests the /a/<code> link out of the injected feed_item, and requests it a median of 54 hours later from a different address. Every other check passed: the impression exists, the campaign matches, the address never repeats inside the dedupe window. It booked as free-tier delivery at ~1,100 clicks every four hours, and /dashboard/ads?range=4h read a 101% CTR because those impressions sat two days outside the window and were mostly flagged duplicate. Nothing billed, but the paper auction was being steered by it. Click validity now also refuses a cited impression that is older than its audience could plausibly still be looking at: 6h when it was served to a browser (real browser clicks over 30 days: p90 2.7 min, none past 6h), 24h for a terminal (non-crawler terminal clicks: 96% within a day), and no ceiling for a feed reader, which keeps an unread item for as long as the subscriber leaves it. Refused clicks land in the existing invalid bucket that ad_slot_totals already reports, so they stay visible without counting as delivery. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
ThreatCrush Security Scan48 finding(s) HIGH/CRITICAL: 2 | MEDIUM: 31 | LOW: 15
Snippets are redacted; ThreatCrush never prints matched credential material. |
ralyodio
added a commit
that referenced
this pull request
Sep 28, 2026
…#329) #264 marked a click that trails its impression past the device ceiling as invalid, but still wrote a row and still 302'd to the advertiser. That is the reward the feed-link harvester keeps coming back for: it fetches feeds with a Chrome UA, keeps the /a/<code> links, and replays them from fresh IPs days to weeks later. Last 7 days on prod: 13,178 of 13,513 clicks were exactly that, 0 of them valid. A stale click now gets a 410 with no link, no-store and noindex/nofollow, and nothing is recorded or charged. Feed-reader impressions keep no ceiling, so a subscriber opening an old item is untouched; no browser click in 30 days has trailed its impression past 6h. Every other invalid click (duplicate, cooldown, forged) is still recorded and redirected as before. Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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.
Why
/dashboard/ads?range=4hread 101% CTR on 2026-09-22. Nobody is gaming the network for money (charged and earned are both 0); it is the same distributed Singapore headless-Chrome crawler documented on coinpayportal's explorer, now crawling rssamplifier.com.It fetches rssamplifier's feed documents with a plain Chrome user agent (so the server-side impression books as
device=desktop), harvests the/a/<code>link out of the injectedfeed_item, and requests it a median of 54 hours later from a different rotating address. Every existing check passes: the impression exists, campaign and slot match, device is not a bot, the IP hash never repeats inside the 6h dedupe window.ad_charge_clicktakes the self-deal branch and writes it as a free-tier click, which the dashboard counts as delivery.The ratio goes past 100% because the click lands in the 4h window while its impression was minted two days earlier, and ~90% of those impressions are
duplicate=true, which the impressions denominator excludes while the numerator keeps the click.Real money never moved, but the paper auction was being steered by it: 43,185 paper cents in one 4h window.
The evidence that picks the ceilings
30 days of
ad_clicksjoined to their impression,device <> 'bot':What changes
assessClickValiditynow also refuses a cited impression that is older than its audience could plausibly still be looking at, keyed on the impression'sdevice:Refused clicks get reason
stale_impressionand land in the existing invalid bucket (valid=false, tier='paid') thatad_slot_totals.invalid_clicksalready reports, so they stay visible without counting as delivery or charging paper.Effect on live data (30 days)
Removes 37,074 of 37,128 Singapore feed clicks and 625 of 629 Singapore terminal clicks. Costs 0 real browser clicks, 34 non-SG terminal clicks past 24h (most of which sit past 7 days and look like the same class), and no feed-reader clicks.
Tests
tests/contract/ads-click-validity.test.tscovers the crawler shape (browser impression, 54h later), the boundary just past 6h, a terminal at 12h and 2 days, a feed reader at 9 days, and null/garbage timestamps. Full suite: 194 files, 2,420 tests pass;tsc --noEmitclean.No migration. Deploy is enough.
🤖 Generated with Claude Code