Rule click_velocity, read from the engine code

Click fraud detection by click speed

Click fraud detection here starts with speed: 50 or more counted clicks from one IP address in an hour is not a person. When a sale's own click came from such an address, the engine holds the sale and the commissions from that burst.

By the AffiliateTracking teamUpdated 5 min read

Fraud page on demo data: held commissions, each with the rule that held it and Release and Uphold buttons, above the verdicts that explain each hold.

The fraud queue in the product, running on demo data.

The short answer

The rule counts clicks from the same IP hash in the hour before the sale, across all affiliates. At 50, it holds the sale. It also holds commissions credited from that affiliate's clicks in the burst, up to 200 clicks.

How the rule works

Read from internal/fraud/engine.go. The code fixes the thresholds. No setting changes them.

  1. 01The sale's own click

    Every credited sale remembers the click that brought it. The engine looks up that click's IP hash and counts every click from it in the past hour.

  2. 02Known bots don't count

    The engine stores clicks from known crawlers and HTTP libraries but leaves them out. The 50 counts only clicks that reached your stats.

  3. 03The burst's money too

    The engine also holds commissions credited from this affiliate's clicks in the burst. A faked click trail can't cash out through a later sale.

The exact logic

// internal/fraud/engine.go, ClickVelocity (condensed)
SELECT COUNT(*) FROM clicks
 WHERE ip_hash = <the sale's click> AND exclude_stats = 0
   AND ts > now - 1 hour
if n >= 50 {
    hold(commission)
    hold(commissions credited from this affiliate's clicks
         in that burst, up to 200 clicks)
}

Condensed from the Go source in v0.5.0 (main 4f87f77). Comments are ours.

The signals

  • 50 or more counted clicks per IP hash in 1 hour
  • Counts all affiliates' clicks
  • Burst commissions held too
Hold scope. It holds the commission being screened, plus commissions credited from the flagged clicks, up to 200 clicks. Nothing else moves.

Our data

We ran the rule at its threshold

We ran 2 fixtures through the real engine on 3 Oct 2026: 1 below the line, 1 at or past it. These are the results and the engine's own words.

click_velocity · 2 fixtures · fresh SQLite each
Each fixture run through the real engine, and whether click velocity fired
FixtureResultThe engine's reason
49 clicks from one IP hash in the last 60 minutesSilentNo verdict
50 clicks from one IP hash in the last 60 minutesFired50 clicks from the same visitor in the last hour
50 clicks in an hour is one click every 72 seconds from one address, for a full hour.
Click velocity: where the rule fires Threshold chart: counted clicks from one ip hash in 1 hour. The engine stayed silent at 49 and fired at 50. The line sits at 50. Counted clicks from one IP hash in 1 hour Fires at 50 Green: 49, silent Red: 50, fires 080
Where click velocity fires, from the fixtures above. Engine v0.5.0 (main 4f87f77), run 3 Oct 2026.

Method: one Go test against engine v0.5.0 (main 4f87f77), a new SQLite database per fixture, dry run so nothing was held. Re-run with go test ./internal/fraud/ plus the fixture list above.

What lands in your queue

When click velocity fires, the verdict shows the rule, who it's about and what it saw. Release or uphold is your call, not the engine's.

Fraud queue · click_velocity · demo dataMade-up numbers, real wording
Example held commission after click velocity fired, on demo data, with the engine's reason text
PartnerWhat it sawCommissionResult
Affiliate 3163 clicks from the same visitor in the last hour$87.20Commission held
heldWaits for youThe commission stays out of payouts until you decide.
releasedPaid normallyIt goes into the next payout.
upheldNot paidThe engine cancels it and takes the money back. Already paid? Use a refund.

In the wild

Scripted traffic runs at volumes no person can.

  • Case: White Ops reported in Dec 2016 that Methbot faked 200 to 300 million video ad impressions a day. That was worth $3 million to $5 million daily. Source: The Hacker News, 20 Dec 2016.
  • Sentence: Its operator, Aleksandr Zhukov, was sentenced to 10 years in prison in Nov 2021. Source: CyberScoop, 10 Nov 2021.
  • Stat: Automated traffic made up 51% of web traffic in 2024, passing human traffic for the first time in a decade. Source: Imperva 2025 Bad Bot Report.

Each item re-read against its linked source on . Items we couldn't verify were cut.

Limits, and how attackers try to beat it

  • IPv6 rotation beats it by default. One phone line can hand out many IPv6 addresses. Setting AE_IP_MODE=trunc24 counts by /48 network instead.
  • It only fires on a sale. A burst that never converts is noise in your stats, not a hold.

Spreading a burst over many addresses costs proxies. Cheap proxies usually live in hosting ranges, which the share of clicks from server ranges measures. Scripts that skip browser headers land in suspected-bot click share.

Related rules

Thresholds checked against the code on . Windows roll with each sale.

Click velocity questions

Does it see my visitors' real IP addresses?

No. The engine stores a keyed hash of each IP, never the address. The rule only checks whether two hashes are equal.

Can a rival point a burst at my best affiliate?

Clicks alone hold nothing. The rule runs when a sale credits, and it holds that sale plus commissions from the burst's own clicks.

When does the rule run?

On every credited sale, in the same database transaction as the credit. A sweep every 5 minutes also re-checks affiliates active in the last hour.

What does a hold cost me?

Nothing but time. A held commission stays out of payouts. Release it and it pays in the next payout. Uphold it and the engine cancels it and takes the money back.

Can I test it without holding anything?

Yes. Set AE_FRAUD_DRYRUN=1. The engine records each verdict and holds nothing.

Who wrote this

The AffiliateTracking team writes these pages from the engine's own code. Every threshold here is pinned by a test in the repository. Spot a mismatch? Tell us and we'll fix the page or the code.

This rule, on every sale,
before the payout.

Self-host for free, or let us run it for you.