← Docs Docs

Click Abuse Protection

Invalid traffic does not stop at the impression. A bot that loads your page can also click your ads, and a competitor or a click farm can hammer a single ad unit to drain a budget or to manufacture an invalid-click pattern that gets your AdSense account flagged. PubSentry watches clicks on your ad slots, classifies each one, and recomputes that verdict server-side so a forged beacon cannot lie its way to "valid."

This page covers what the tag observes, the five click classes, how the server hardens the verdict against tampering, and where the data shows up.

Why click abuse matters separately from impression IVT

Impression IVT and click abuse are different failure modes with different consequences:

  • Clawbacks. Networks reverse earnings on clicks they later judge invalid — unexplained revenue drops you cannot reconcile.
  • Advertiser trust. Click farms and rapid-repeat clicks waste advertiser budget, which erodes the demand that pays your RPMs.
  • Account risk. A burst of invalid clicks on your inventory is one of the fastest ways to trigger an ad-network policy review — the kind that ends in a suspension. Catching the pattern and being able to show it is part of protecting the account, not just the revenue.

The visitor's impression-level verdict still drives block-before-serve; click tracking adds a dedicated lens on what happens after an ad renders.

What the tag observes

The click tracker is part of the same single async tag — there is nothing extra to install:

<script async src="https://pubsentry.com/t.js" data-site="st_xxxx"></script>

On load, the tag attaches a single passive, capture-phase click listener to the window. For every click it walks up to eight ancestors looking for an ad element — an AdSense ins.adsbygoogle, a Google Publisher Tag div-gpt-* slot, an ad iframe, or a container whose id/class matches ad-slot patterns. Clicks that are not on an ad slot are ignored entirely; only ad-slot clicks are measured.

For each ad-slot click the tag records three things and nothing more: the time from page load to the click, the count of ad clicks in this session, and the visitor's current impression-level verdict (allow / monitor / block). Like everything in the tag, the listener is wrapped so it can never throw into your page — a failure in click tracking will never break a click or an ad.

The five click classes

Every measured click is sorted into one of five classes:

  • invalid — the visitor's impression verdict is already block. A bot that we scored as invalid then clicked an ad. This is the highest-confidence invalid click.
  • abusive — rapid-repeat clicking. More than three ad clicks in one session, or (server-side) a fingerprint clicking across sessions at a click-farm rate.
  • accidental — a click that lands too soon after load (under 800ms) to reflect genuine intent — the classic fat-finger mis-click on a sticky or interstitial unit.
  • bounce — a click followed by an immediate exit, signalling the click did not lead to engagement.
  • valid — none of the above. A normal, human, intentional click.

These thresholds are deliberately conservative. The point of click classification is to explain and report, not to silently void a real reader's click — consistent with the FPR=0 principle that governs the whole product.

The server is the source of truth

This is the part that makes the click data trustworthy. When the tag detects an ad-slot click it POSTs a compact ClickBeacon to the click endpoint — and the server never trusts the classification field in that body. A bot could trivially POST {"classification":"valid"}. So the ingest service throws the submitted class away and recomputes it from the measured fields (time-to-click, session click count) using the same rules.

The server also has a signal the tag cannot see: cross-session click velocity. It keeps a per-fingerprint click rate in Redis, keyed independently of impression velocity. If a single fingerprint is clicking ads faster than a human plausibly could across all its sessions, the server escalates the class to abusive with a "click-farm pattern" reason — even if each individual session looked tame. The tag, scoped to one page, can never observe this; the server's view across the whole network is the trump card against distributed click farms.

This recompute-and-escalate step is best-effort and timeout-guarded: if the velocity lookup is slow, the click is still stored with its measured-field classification. The click endpoint is also rate-limited per peer and responds immediately, so a flood of click beacons can never back up the pipeline.

Privacy

Click beacons carry the same privacy posture as the rest of PubSentry. The tag sends only client-knowable fields — the ad unit id, timings, session counts, and hashed entity identifiers (the device fingerprint uses a non-PII fnv1a hash). Raw IP and User-Agent are never sent by the tag; where the server uses the request IP for velocity, it is hashed with HMAC-SHA256 and then dropped, never stored in the clear.

Where the data shows up

Classified clicks are written to a dedicated clicks table and surfaced in the dashboard:

  • A Click Abuse view breaks down your clicks by class so you can see what share are abusive, invalid, or accidental versus valid.
  • A per-ad-unit table ranks slots by abusive-click volume, so you can see exactly which unit a click farm is targeting and the worst single-session click count observed.

Because the classification carries its reasons — for example "rapid repeat (5 ad clicks this session)" or "12 ad clicks/min across sessions for this entity (click-farm pattern)" — every label is explainable. You are never staring at a number you cannot justify to a network or an advertiser.

What is not built yet

To stay honest about the boundary:

  • Click abuse does not block. Today the system classifies, escalates, stores, and reports clicks. Block-before-serve operates at the impression level — a visitor we score as invalid never gets an ad to click in the first place, which is the strongest click-fraud defense. There is no separate "void this click" enforcement step beyond labelling it.
  • bounce and post_click_dwell_ms exist in the data contract but post-click dwell is not yet measured end to end, so bounce is rarely assigned in practice.
  • Programmatic access is coming. The endpoints that feed the dashboard are session-scoped to your account, not a documented public integration. A stable public API and outbound webhooks for click-abuse events are on the roadmap (coming), not shipped. If you need to pull click data into your own systems now, tell us what you are building so we scope it honestly.

The short version

Install the one tag, leave it in Block mode, and PubSentry watches every click on your ad slots, classifies it from measured fields the server recomputes itself, escalates click-farm velocity it can see across sessions, and reports the result per ad unit with a reason you can defend. It is the click-side complement to block-before-serve: stop the obvious bots before the ad fires, and explain every abusive click that gets through.

Stop invalid traffic before the ad fires. Score every visitor, block the invalid ones pre-serve, protect your account. Free for your first 500 pageviews.
Start free →