Guides
Traffic and crawlers without GA4
One script tag records page views, referrers and real-user vitals; a worker hook records the crawlers that never run JavaScript. First-party, no cookies, no third-party account.
Updated 2026-11-08
On this page
Guide · first-party telemetry
Page views, referrers, real-user vitals and crawler hits without GA4 and without a third-party account. No cookies, no IP addresses stored, daily-rotating visitor hashes.
How to read the numbers
- Sessions come from the collector only. One closed tab is one session, keyed by a random id that lives in
sessionStorageand dies with the tab. - Page views are counted per path, query string stripped, so
?utm=variants do not split a page. - Vitals are sampled: about one in ten visitors reports LCP and CLS. A metric stays empty until a page has 20 samples in the window — a p75 of three visits is noise, not a measurement.
- Crawlers never sum two sources. When both the probe and Cloudflare saw the same bot, the probe row wins because it carries the path.
Agent identities before you wire the probe: GPTBot, ClaudeBot and PerplexityBot each list the documented user agent, robots.txt token and IP verification steps.
Any site: one script tag
Paste this before </body>. It sends one beacon per visit on page hide — a complete session, not a request per click.
Check it worked: Load any page, wait a few seconds, close the tab. The Traffic block shows a session within a minute.
Next.js App Router
Use next/script in the root layout so the tag survives client-side navigation. The collection endpoint is same-origin with your dashboard, so no proxy is needed.
Check it worked: Navigate between two routes, then close the tab. The session's page count is 2, not 1.
Cloudflare Worker: crawler probe
GPTBot, ClaudeBot and PerplexityBot do not run JavaScript, so page tags never see them. Forward each request to the probe endpoint from your worker; unknown user agents are dropped server-side. Report the real response status after the fetch — without it the invalid-crawl block stays unavailable.
Check it worked: Curl your site with a GPTBot user agent. The Crawlers block names GPTBot and the path you hit; the Invalid crawls block lights up once statuses are reported.
Probe as an npm package
Prefer a dependency over a pasted snippet? @visdenda/agent-watch wraps Next.js, Cloudflare Workers, Bun, Deno, edge runtimes and Node servers, handles waitUntil, and keeps the same fire-and-forget contract. A page script alone never sees AI crawlers — the npm guide marks which setups can.
Get your token from Search → Sessions → Traffic. Rotating it revokes the old one immediately; the token is a routing key, not a secret — it is visible in your page source. The page beacon checks Origin per site, and the probe (server-side, no Origin header) cannot; the real limit there is the daily cap, and forged reports can only pollute your own dashboard until you rotate the token. Installing either tag on a site you control also makes you responsible for disclosing the collection in that site's privacy policy — the privacy policy lists exactly what each channel sends.