Skip to main content
AI traffic tracking shows which AI systems fetch your pages and which people arrive from an AI answer. A small request-capture SDK on your site sends a neutral request envelope to Notra; all classification happens at ingest. The results appear on the Traffic page (titled AI Traffic) and under /geo/traffic in the API.

What is captured

Every captured request is classified into one of two tracked visitor types:
  • AI crawler: bots fetching your pages to train models or build a search index. Each crawler carries a Purpose: Model training (collects pages for training corpora), Search index (builds the index an AI answer engine searches), or Cited in answer (fetched while an assistant was answering someone).
  • AI referral: a person who clicked through to your site from an AI answer. Detection is based on the referrer host, for example chatgpt.com, perplexity.ai, gemini.google.com, claude.ai, copilot.microsoft.com, you.com, chat.deepseek.com, chat.mistral.ai, grok.com, and chat.qwen.ai.
Requests classified as human are discarded at ingest and never stored. Each stored event carries the source, the agent, the purpose, a Confidence of Verified, Reported, or Heuristic (how the agent’s signature was sourced), the path and host, the country, whether the client asked for Markdown, and a journey id.

Journeys

A journey groups the pages one agent read in a session. Two kinds exist:
  • Tagged journey: the agent followed a link carrying an ntr query parameter that your site minted. This is exact.
  • Fingerprinted journey: requests were matched by a heuristic: the source, a truncated IP prefix, and a 30 minute time bucket (10 minutes and the full IP for assistant browsing), hashed with a salt that rotates daily. This is an estimate.
Journeys appear on the Overview page under the Journeys section and in the API. The Agent journeys table has Journey, Source, Pages, Unique, Span, Last seen, and Path columns.

Set up the tracker

1

Get your token

Open Traffic in the GEO sidebar. Until the first event arrives the page shows No activity yet with the full install panel: Install the package, Set your token, and Add the proxy. The token is shown in the Set your token section. The panel also has a Copy agent prompt button that copies an instruction block you can paste into a coding agent.From the API, reading the snippets needs traffic.read and issuing the token needs traffic.write:
Both return ingestUrl, snippet (the Next.js snippet), and snippets with next, nuxt, tanstack, astro, sveltekit, and netlify keys. The token endpoint adds token. The ingest routes are organization-level; pass projectId to bind the token to one project or omit it to track the whole organization. Issuing a token does not invalidate tokens issued earlier. Install the same project token on every domain the project tracks; add extra hostnames under Tracked domains in GEO settings.
2

Install the package

The package has zero dependencies and no Node APIs in the core, so it runs on edge runtimes. Install with npm, pnpm, or yarn if you prefer.
3

Set the environment variable

Add the token as NOTRA_GEO_TOKEN in your site’s environment variables, locally and at your hosting provider. Never hardcode or commit it.
4

Add the proxy

Pick your framework. These are the snippets the dashboard generates; endpoint is the origin the SDK posts to and the SDK appends /api/geo/ingest.
proxy.ts
Use proxy.ts on Next.js 16 and middleware.ts on earlier versions. geo(request) never throws and never blocks the response.
5

Deploy and wait for the first visit

The Traffic page switches from the install panel to the dashboard as soon as the first AI crawler or referral is stored.

Tracker options

Only GET requests that look like pages are captured. Anything under /_next/, /_nuxt/, /_vercel/, /_astro/, /_app/immutable/, /static/, and any path ending in a common static extension is skipped. llms.txt and llms-full.txt are always captured. exclude entries can be a string prefix, a RegExp, or a (request, url) => boolean function. The envelope contains the timestamp, method, URL, client IP, edge location headers when present, referer, user agent, accept and accept-language headers, and a request id. No request body, no cookies, and no other headers are read or sent. The POST uses keepalive and a 2 second timeout.

Journey tagging

@usenotra/geo/markdown exports mintJourneyId, getJourneyId, and tagMarkdownLinks so the links you hand to an agent in Markdown carry an ntr id and every follow-up request lands in the same journey. On Next.js you can instead pass tagLinks: true to createGeoProxy; the proxy then tags Markdown responses (.md, llms.txt, llms-full.txt) served to known AI agents on the way out, and html: true extends that to the anchors in HTML pages. Human visitors and search crawlers always receive the untouched origin response. Tagging needs no token.

Rotating the token

Rotation invalidates every tracking token previously issued for the organization and returns a fresh one. Deployments still sending the old token stop being accepted immediately, so update NOTRA_GEO_TOKEN everywhere before you rotate.

The Traffic page

Once events arrive the page shows three sections, each honouring the range picker:
  • A hero row with Crawlers, Referrals, and Total visit counts, each compared “vs. previous period”, and a daily trend chart.
  • Sources: three groups — Crawlers (training and search-index bots), Cited (assistant-browse fetches while an engine answered someone), and Referrals. Columns are Source, Purpose, Visits, Markdown (visits that asked for Markdown; crawlers and cited only), Pages, and Last seen. Sources group by operator, for example OpenAI, Anthropic, Google, Perplexity, Microsoft, Meta, Instagram, Amazon, Apple, ByteDance, and Common Crawl. Instagram is its own source, not folded into Meta.
  • Top pages by AI source: Page (host and path), Sources, and Visits. When a project tracks more than one domain, a domain filter narrows the table.
  • Recent citations: the live event log with All visitors (AI crawler, AI referral) and All purposes (Model training, Search index, Cited in answer) filters. The domain filter on top pages also narrows this log. Live updates refresh every few seconds and can be paused.

Reading traffic from the API

All paths below are prefixed with /v1/projects/{projectId} and need traffic.read. Windowed endpoints accept days (1 to 365) or from/to (YYYY-MM-DD). visitorTypes and categories on the log endpoint are comma-separated lists. categories accepts training-crawler, search-index, and assistant-browse.
Every traffic response includes configured. When it is false the traffic backend is not configured for the deployment and the payload is empty rather than an error.

Limits to keep in mind

Crawler classification relies on user agent signatures. Anyone can send a crawler’s user agent string. The Confidence value tells you how the signature was sourced; where an operator publishes IP ranges or a reverse DNS method, the signature table points at it, but Notra does not verify IPs at ingest.
The Cited in answer purpose means an assistant fetched the page while answering someone. It does not prove the answer quoted or linked the page.
Agents that cannot be honestly identified by user agent are deliberately absent from the signature table, including Pi, ChatGPT Atlas, Google-Extended, and Applebot-Extended. Traffic from them is either discarded as human or attributed to a generic browser.
AI referrals are recognised by referrer host. Clicks from apps that strip the referrer, or from hosts not in the list, are not counted.
Only journeys that followed a tagged ntr link are exact. Fingerprinted journeys group requests by heuristic and can merge or split real sessions.
If you set sample below 1, every count in the Traffic page and API reflects the sampled fraction; Notra does not scale the numbers back up.

Get the install snippets

API reference for the ingest setup route.

Agent feedback

The same SDK ships an MCP feedback tool for the agents using your product.
Last modified on September 18, 2026