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
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.
- 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.
- 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.
- 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
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.
| Fixture | Result | The engine's reason |
|---|---|---|
| 49 clicks from one IP hash in the last 60 minutes | Silent | No verdict |
| 50 clicks from one IP hash in the last 60 minutes | Fired | 50 clicks from the same visitor in the last hour |
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.
| Partner | What it saw | Commission | Result |
|---|---|---|---|
| Affiliate 31 | 63 clicks from the same visitor in the last hour | $87.20 | Commission 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.