Every visitor that hits a page running PubSentry gets a verdict: a single invalid-traffic (IVT) score from 0 to 100, a class, an action, and the exact list of reasons that produced it. This page explains how that number is built — the rules, the aggregation math, the reputation blend, and the thresholds that turn a score into "allow," "monitor," or "block." There is no black box: the engine is a transparent weighted ensemble, and every block carries the evidence that justified it.
One engine produces this verdict everywhere — in the browser tag, at the edge, and on the server. That shared engine (@pubsentry/scoring) is the same code in all three, guarded by a parity test, so a 5ms decision in the browser uses the identical logic as a server decision with full IP intelligence.
If you have not installed yet, it is one async tag:
<script async src="https://pubsentry.com/t.js" data-site="st_xxxx"></script>
The signal vector
Scoring starts with a signal vector — a bundle of evidence about the visitor. Some signals are collected in the browser by the tag (automation tells, environment coherence, behavioral and temporal signals, honeypot interaction). Others are derived server-side from the request: the IP's network type (datacenter, VPN/proxy, Tor, residential), its ASN, whether the User-Agent matches a known bot, and the entity's request velocity across the network.
A privacy note that matters for accuracy: the raw IP and User-Agent are hashed server-side with HMAC-SHA256 and then dropped — never stored in the clear. The network classification (datacenter/ASN/geo) comes from an offline iptoasn dataset, so today it detects hosting and datacenter origins but does not flag residential proxies, consumer VPNs, or Tor by IP reputation alone. Those origins stay unknown unless another signal gives them away.
Rules: hard, heavy-soft, and soft
The engine runs a registry of rules over the signal vector. Each rule is a pure function that either fires — returning a weight and a plain-English reason — or stays silent. Rules fall into three tiers.
Hard rules are unambiguous invalid-traffic tells. When one fires, the score is pinned to 100 and the verdict is an instant block, classed as general invalid traffic (GIVT). These are the things only automation does:
navigator.webdriver === true(browser automation flag)- A headless/automation framework global present (Selenium, Phantom, Nightmare)
- A known bot/crawler User-Agent signature
- Honeypot interaction — the visitor touched an invisible decoy only bots find
- ChromeDriver/WebDriver injection markers (
cdc_, selenium artifacts) - A Tor exit node origin
There is no ambiguity in these, so there is no FPR risk in blocking them. This is the bulk of the junk hitting most publishers, and it is gone the moment you are in Block mode.
Heavy-soft network heuristics are strong but not certain. A datacenter IP is a powerful invalid-traffic signal — but real people egress through datacenter-adjacent IPs every day (corporate VPN/SASE, iCloud Private Relay, Cloudflare WARP). So a datacenter origin is a heavy soft weight (55), not a hard block: on its own it only pushes a request into the monitor band; combined with any other tell it blocks. Critically, if the ASN is on the allowlist (Apple Private Relay, known corporate egress), the rule does not fire at all. That allowlist is the front-line false-positive guard.
Soft heuristics are the sophisticated-IVT (SIVT) layer — each weak on its own, meaningful in combination. A sample with weights:
- A native browser function was patched — stealth automation tooling (70)
window.chromeabsent on a UA that claims Chrome — spoofed (45)- User-Agent inconsistent with platform/features (up to 50, scaled by incoherence)
- VPN/proxy network origin (40); inconsistent screen/window geometry (30)
- Abnormal request velocity for the entity (up to 60, ramped with rate)
- Page preloaded/prerendered or never visible (25); no interaction after dwell (22)
- Smaller corroborating tells: language/timezone mismatch, permission anomalies, incoherent pointer/touch (18-20)
These weights are deliberate, conservative priors — biased toward not blocking when uncertain. They have not yet been calibrated against large-scale real traffic; that calibration is part of the ML moat (M9, coming), and it can only tighten the engine, never loosen the FPR-zero guarantee.
Aggregating soft weights: probabilistic OR
Simply adding the soft weights up would let a stack of weak signals race past 100 and false-block a real human. Instead the engine combines them as a probabilistic OR:
score = 1 − Π(1 − wᵢ/100)
Each weight is treated as an independent probability of "invalid": multiply the complements, take one minus the product. Every additional weak signal raises confidence, but with diminishing returns — the score asymptotically approaches, without reaching, certainty. Soft-only scores are capped at 99, so only a hard rule can produce a certain 100. That asymmetry is deliberate: certainty requires unambiguous evidence.
Blending cross-site reputation
If the entity is known to the reputation network — flagged on other sites — that evidence is blended in. The rule is one-directional: reputation can only raise a score, never lower it. A clean-looking request from a known-bad entity is still suspect, so the engine takes the max of the local and reputation scores.
There is a deliberate false-positive guard in this blend. IP addresses are shared and recycled, so a single site's flag on an IP must not hard-block innocent users elsewhere on that same IP. Single-site IP reputation is therefore capped to the monitor band — it can warn but not block on its own; it takes corroboration across two or more sites for an IP to act at full strength. Device fingerprint reputation, by contrast, is per-device and acts at full strength immediately. That cross-device, cross-site corroboration is the network moat, and it grows stronger with traffic.
From score to action: safety-mode thresholds
A 0-100 score becomes an action through two thresholds set by the site's safety mode:
| Safety mode | Block at | Monitor at |
|---|---|---|
| conservative | 92 | 65 |
| balanced | 78 | 48 |
| aggressive | 58 | 32 |
A score at or above the block threshold blocks; at or above monitor (but below block) it monitors (recorded, not suppressed); below that it is allowed. The default is balanced. The thresholds are conservative by design, because the product's first principle is that blocking a real human — a false positive — is the worst possible failure. Move toward aggressive only when you have a specific abuse pattern and have checked the retroactive blast-radius preview in Rules.
Classification
The verdict's class follows from how it scored. An allowed request is clean. A blocked or monitored request is givt if a deterministic (hard) rule fired or the reputation flags say so, and sivt otherwise — the heuristic, harder-to-catch tier. Content-policy findings carry their own policy_risk class from the policy scanner.
The verdict and its reasons
The output is a verdict: the ivt_score, the class, the action, where it was decided_at (local, edge, or server), the gate latency, version stamps — and the reasons. Reasons are the literal rule hits that fired, each with its signal name, weight, and plain-English note, sorted most-important-first. This is the transparency contract: a block is never unexplained. Those reasons are exactly what the dashboard renders in the Live Feed and the Request Inspector, so you can always answer "why was this visitor blocked?" with the engine's actual evidence — never a number invented after the fact.
What it catches, honestly
Obvious, general invalid traffic — known bots, datacenter origins, automation tells, declared crawlers — is caught at near-100% recall with zero false positives. Sophisticated invalid traffic running from clean residential IPs with no behavioral tells is only partially caught today, by design: blocking it aggressively would risk blocking real humans. That gap closes as the reputation network corroborates entities across sites and the ML layer calibrates on real traffic. PubSentry will never claim "100%."
