Skip to Content

Install crawler reporting

Crawler reporting runs on your server, not in the browser. If you haven’t read why, start there. The short version is that AI crawlers never execute JavaScript, so the <head> snippet can never see them.

This is a second, separate install. Keep your tracking snippet exactly as it is. The two halves measure different traffic.

1. Get the whole thing from the dashboard

Open Settings → Tracking → AI crawlers. That section is the fast path — the snippets on this page are the same ones it generates, and it fills in your domain, your ingest URL and your key for you:

Click Create API key

You need one key per site. The same snw_live_… secret authenticates server-side events, identify and crawler reporting, so if you already have one in SNOW_API_KEY, you are done with this step — there is no separate crawler credential.

Creating one here fills it into every snippet in that screen at once. It is shown once, so copy before you navigate away.

Pick where your site runs

Next.js, Astro, Express, Hono, a Cloudflare Worker, WordPress or plain PHP. The snippet re-renders with your key already in place.

Copy, paste, deploy

Then run the curl at the bottom of the section to force a test hit.

Store the key as a server-side environment variable (SNOW_API_KEY). Never use a browser-exposed prefix like NEXT_PUBLIC_, VITE_ or PUBLIC_. Those are inlined into your client bundle, which publishes the key to everyone.

Want least privilege instead? On the API keys tab you can untick Events and Identify and mint a key that can only report crawler hits — worth doing for a key you paste into a CDN edge worker, where it sits outside your application’s own secret store.

The rest of this page is the manual version, for adapting the install by hand. Replace the <YOUR_SNOW_API_KEY> placeholder with your key.

2. Install the middleware

Snow speaks the Beacon  wire protocol. Beacon is an MIT package you install from npm; collector: "snow-analytics" is the only Snow-specific line. If you already run Beacon, changing that one line is the entire migration.

That is the whole config. There is no siteUrl — your key belongs to one site, so Snow resolves it — and nothing to switch off:

  • Reporting only is the default. Beacon can also serve Markdown versions of your pages; asking for analytics alone means no page’s response ever changes.
  • No 406s. A beacon that serves no twins never refuses a request whose Accept header names neither HTML nor Markdown, so your own JSON endpoints are untouched.

Needs @snowseo/beacon 0.1.8 or later. On 0.1.7 and earlier, collector is ignored and createBeacon throws without a resolve — pin the range as shown above rather than relying on whatever is already in your lockfile.

Self-hosting Snow? Use endpoint: "https://your-api/api/beacon/hits" instead of collector. Use the full path, not the bare origin: beacon fills in its own default (/beacon/hits) only when the endpoint has no path, and Snow mounts under /api, so a bare origin resolves to a URL Snow doesn’t serve and every batch fails with 401.

npm install @snowseo/beacon@^0.1.8
beacon.ts
import { createBeacon } from "@snowseo/beacon"; export const beacon = createBeacon({ analytics: { key: process.env.SNOW_API_KEY!, collector: "snow-analytics", }, });
proxy.ts (middleware.ts before Next 16)
import { beaconAdvertise } from "@snowseo/beacon/next"; import { type NextFetchEvent, type NextRequest, NextResponse } from "next/server"; import { beacon } from "./beacon"; export default async function proxy(request: NextRequest, event: NextFetchEvent) { return beaconAdvertise(beacon, request, NextResponse.next(), event); }
.env
SNOW_API_KEY=snw_live_...

3. Verify the install

Open Settings → Tracking → AI crawlers. The status pill at the top turns green the moment your server posts its first batch, even if no crawler has visited yet.

That distinction matters more than it sounds. Without it, “not installed” and “installed, but quiet” look identical, and an empty report is ambiguous. With it, green means you’re done and the zero is real.

To force a hit immediately:

curl -A "GPTBot/1.0" https://example.com/

It should appear on the AI Traffic section within a minute, attributed to OpenAI with the Training intent.

Common problems

A CDN or cache answers before your server runs

If Cloudflare, Fastly, Vercel’s edge cache, or a WordPress page-cache plugin serves a cached copy, your application code never runs, so the hit is never reported. Crawlers hitting popular pages are exactly the requests most likely to be cached.

Fix: install at the edge instead. On Cloudflare, use the Worker, which runs ahead of the cache and sees everything.

Nothing arrives at all

  • Check the key is present in the server’s environment, not the client’s.
  • Check outbound HTTPS to api.snowanalytics.app isn’t blocked by an egress firewall.
  • Check you installed it in the app that actually serves your public pages. In a monorepo that is usually not the same package as the one holding <head>.

It’s installed but shows zero crawlers

That’s a real answer, not a bug. Googlebot and Bingbot are deliberately excluded, so a well-indexed site can still show nothing until an AI crawler visits. New and low-traffic sites often wait days for a first GPTBot fetch.

Don’t install it twice

Middleware and an edge Worker covering the same requests will double-count. Pick one.