Most PubSentry problems trace back to a handful of root causes: the tag is not actually on the live page, the site ID is wrong, a Content-Security-Policy is blocking the script or beacon, or you have hit the free-plan pageview budget. Because the tag is fail-open by design — it never throws into your page or delays an ad — a misconfiguration usually shows up as silence (no data) rather than an error. The mindset here is "follow the beacon," not "find the exception."
For a clean install reference, see Getting Started and Installing the Tag. The install you should be matching is:
<script async src="https://pubsentry.com/t.js" data-site="st_xxxx"></script>
Install won't verify / no first beacon
The Install screen watches for the first beacon and flips to "verified" within seconds of a real pageview. If it stays pending, work down this list in order:
- Is the script actually on the live page? View source on the deployed URL (not your editor, not a cached preview) and confirm the
src="https://pubsentry.com/t.js"line is present. A caching layer, an A/B tool, or an HTML-minify plugin stripping unknown tags is a common culprit. - Does
data-siteexactly match your site ID? It must be thest_…ID from your dashboard, character for character. A trailing space or a copied placeholder (st_xxxx) means the beacon has no valid site to attribute to. - Are you on a real domain? A
file://page orlocalhostorigin may carry no usable origin and get dropped. Test on the actual site. - Open the Network tab. You should see
t.jsload (200), then a/v1/beaconrequest. Ift.js404s, the src is wrong. If it loads but no beacon fires, jump to the CSP section below. - Check the free-plan budget. Beacons stop counting once you cross the free-plan limit (see "Dashboard paywalled" below).
The beacon is sent with navigator.sendBeacon (with a keepalive: fetch fallback) as a text/plain body — deliberately a CORS "simple request" with no preflight and no credentials, so it survives page unload and never blocks render. Tooling that rewrites or strips sendBeacon will break verification.
The tag loads but no data appears in the dashboard
If t.js returns 200 but Overview and Live Feed stay empty, the beacon is being dropped between the browser and ingest. Check, in order:
- The beacon in the Network tab. Find the
POSTto/v1/beacon. A success returns a 2xx with an empty/tiny body. No request at all usually means a CSPconnect-srcis blocking it (next section); a red/blocked one names its reason in the console. - Ad blockers and privacy extensions. Some block third-party beacons. Test in a clean profile with extensions disabled — if data appears there, it is client-side filtering, not your install.
- The free-plan cap. Past the budget, ingest still serves readers but stops counting beacons toward analytics.
A privacy note: ingest enriches the request server-side (datacenter/ASN/geo from the IP via an offline dataset, device from the User-Agent), then hashes raw IP and User-Agent with HMAC-SHA256 and drops them. A missing raw IP in an event is by design, not a bug.
Content-Security-Policy is blocking the tag
If you run a CSP, you must allow https://pubsentry.com on two directives or the tag silently fails: script-src (so t.js loads) and connect-src (so the beacon, and the click signal if you use click tracking, can POST). A block shows up in the console as a CSP violation naming the directive. The tag needs neither unsafe-inline nor unsafe-eval, and a nonce-based CSP needs no nonce on the script tag — the external t.js is covered by the host allowlist.
Ads still serve when the visitor should be blocked
In Block mode the tag suppresses the ad request before it fires across Google Publisher Tag, AdSense / Auto Ads, Amazon apstag, and Prebid, plus a universal MutationObserver fallback. If invalid visitors still see ads, check:
- Mode is actually Block, not Measure. In Measure mode the tag scores and records everything but suppresses nothing — that is its whole job. Confirm your site's Protection Mode is set to Block. The tag caches per-site config synchronously on boot, so after a mode change, hard-reload to fetch the fresh config.
- You are looking at sophisticated traffic. The engine catches obvious / general invalid traffic (GIVT) — datacenter IPs, known bots, automation tells, declared crawlers — at near-100% recall with zero false positives. Sophisticated invalid traffic (SIVT) from residential IPs with no behavioral tells is only partially caught today, by design: blocking it aggressively would risk blocking real humans (the FPR-zero principle). That gap closes as the reputation network and ML moat accumulate traffic. We will never claim "100%."
- A non-standard ad loader. If your stack injects ads through a method none of the hooks cover, the
MutationObserverfallback handles most cases; tell us if one slips through.
Real visitors are getting blocked (suspected false positive)
A false positive — blocking a real human — is the worst failure in this product, so the defaults are conservative. If you suspect one:
- Open the Request Inspector on the event. Every verdict is explained — the signals and weights that produced it — so you can see why the visitor scored as invalid.
- Check your Safety Mode dial (
conservative→balanced(default) →aggressive). If you moved toaggressivechasing a specific pattern, that tightens thresholds for everyone. Move back towardbalancedunless you have watched the blast-radius preview. - Check your own rules. A hand-written block rule or IP range may catch more than intended. Use the retroactive blast-radius preview in Rules & IP Management to see who a change would have affected.
- If you still believe the engine blocked a genuine human, that is exactly the report we want — send us the event to investigate against the human corpus.
The dashboard is paywalled / "over limit"
Every account starts on the free plan: 500 lifetime pageviews — a hard budget, not a time-limited trial. Once you cross it, the data screens paywall while billing and account screens stay reachable. Your readers are unaffected: the tag and ingest keep running fail-open; only dashboard analytics are gated. To restore full access, pick a paid plan (Starter, Growth, Scale) — they differ only by volume (pageviews, sites, history); every detection and DEFEND feature is on every plan, including free. Paid-plan overage is a warning, not a hard lockout — only the free budget hard-gates the dashboard. See Plans & Billing.
Can I call the API to debug?
Not yet. The /v1/* requests in your Network tab power the dashboard but are not a public API: cookie-session-scoped, same-origin only, and free to change with the UI. A documented public API and signed webhooks are on the roadmap (coming), not shipped. For now, debug from the dashboard (Live Feed, Request Inspector, Install), not by scripting those endpoints. See API & Webhooks.
Still stuck?
If the loop still will not light up, gather three things and reach out: the live URL with the tag installed, your st_… site ID, and a Network-tab screenshot showing the t.js load and the presence (or absence) of /v1/beacon. That trio almost always pinpoints the failure in one pass.
