Rule bot_class_gating, read from the engine code

Bot click fraud beyond the known-bot filter

Bot click fraud that gets past the known-bot filter still leaves a trace: requests with no Accept and no Accept-Language header. When half or more of an affiliate's counted clicks in 7 days look like that, and they have 3 sales, the engine holds the sale.

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

Known bots never count. Of the clicks that do count, the rule needs 20 or more in 7 days, half or more suspected bots, and 3 or more sales. It holds the sale and the commissions from the suspected clicks.

How the rule works

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

  1. 01Two classes at the click

    An empty user agent, or one naming a crawler or HTTP library, is a known bot and never counted. Real browsers send Accept and Accept-Language. A click missing both is a suspected bot.

  2. 02Half of at least 20

    The engine counts the affiliate's counted clicks for 7 days. With 20 or more, half or more suspected bots crosses the line.

  3. 03Money follows the clicks

    The rule needs 3 sales in the window. It then holds the sale and the commissions credited from the suspected clicks, up to 200 clicks.

The exact logic

// internal/fraud/rules3.go, BotClassGating (condensed)
// at the click: empty UA or bot token (googlebot, curl, python-requests,
//   headlesschrome ...) = known, excluded from stats
// no Accept AND no Accept-Language header = suspected
suspected, total := counted clicks for the affiliate, last 7 days
if total < 20 || suspected*2 < total { return }
if sales in the last 7 days < 3 { return }
hold(commission); hold(commissions from the suspected clicks)

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

The signals

  • Half or more suspected-bot clicks
  • 20 counted clicks in 7 days
  • 3 or more sales in the window
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.

bot_class_gating · 2 fixtures · fresh SQLite each
Each fixture run through the real engine, and whether bot traffic fired
FixtureResultThe engine's reason
9 of 20 counted clicks suspected, 3 salesSilentNo verdict
10 of 20 counted clicks suspected, 3 salesFired10 of 20 clicks in the last 7 days looked like bots
Exactly half fires. The code checks suspected times 2 against the total.
Bot traffic: where the rule fires Threshold chart: suspected-bot share of 20 counted clicks (%). The engine stayed silent at 45 and fired at 50. The line sits at 50. Suspected-bot share of 20 counted clicks (%) Fires at 50 Green: 45, silent Red: 50, fires 0100
Where bot traffic 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 bot traffic 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 · bot_class_gating · demo dataMade-up numbers, real wording
Example held commission after bot traffic fired, on demo data, with the engine's reason text
PartnerWhat it sawCommissionResult
Affiliate 2731 of 51 clicks in the last 7 days looked like bots$76.50Commission 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

Bots that look like people are now the bigger share.

  • Stat: In 2024 automated traffic reached 51% of web traffic, and bad bots 37%. Source: Imperva 2025 Bad Bot Report.
  • Case: In Mar 2026, Michael Smith pleaded guilty to using AI-made songs and bot accounts to collect more than $8 million in streaming royalties. Source: Decrypt, 20 Mar 2026.

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

Limits, and how attackers try to beat it

  • A script that sends both headers counts as human here. The classifier reads the user agent and two headers, nothing else.
  • Headless Chrome that hides its name in the user agent passes too.

Faking the headers is easy, so this rule is one layer. Scripts usually run from servers, and hosting-range click share checks where they come from. Bots that buy also tend to buy at odd hours, which night-time sales against your program's normal compares.

Related rules

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

Bot traffic questions

Does Googlebot clicking a link hurt my affiliate?

No. Googlebot is a known bot. Its clicks are stored but excluded, and never count toward this rule.

Does it fingerprint visitors?

No. It reads the user agent and whether two standard headers were sent. Nothing runs in the visitor's browser.

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.