Get Started
View .md

Track AI traffic on your site

AI assistants read your website far more often than their answers show it. QuickSEO's AI traffic tracking records every visit from a known AI crawler — which bot, which page, when — so you can see whether ChatGPT, Claude, Perplexity, Google and the rest are actually reading your content.

It works with a small server-side snippet: your server (or middleware) sends QuickSEO a POST for each request, and QuickSEO classifies the user agent against its own registry of known AI crawlers. There's no JavaScript on your pages and nothing for visitors to download — most AI crawlers don't execute JavaScript, which is why analytics tools that rely on a browser script under-count them.

What it tracks

Every recorded visit is classified into one of four categories:

CategoryWhat it meansExamples
AI AnswersA live fetch made to answer a user's question right nowChatGPT-User, Claude-User, Perplexity-User
IndexingSearch and answer-engine indexing crawls that feed retrievalOAI-SearchBot, Claude-SearchBot, Googlebot, Bingbot
TrainingCrawls collecting data for model trainingGPTBot, ClaudeBot, CCBot, Google-Extended
Other AIOther AI-related crawlersDiffbot, GrokBot, Google-CloudVertexBot

The registry covers roughly 50 known crawler user agents from OpenAI, Anthropic, Perplexity, Google, Microsoft, Apple, Amazon, Meta, xAI, Mistral, DuckDuckGo, ByteDance, Baidu, Alibaba, Moonshot, DeepSeek, Zhipu, Cohere, Allen AI, You.com, Common Crawl, and Diffbot.

AI Answers is the category to watch. A hit there means an assistant opened your page while composing an answer for a real person — the closest thing to a "click" AI search has.

Get your tracking ID

  1. In QuickSEO, open your site and go to Settings → AI Traffic Tracking.
  2. Copy the Tracking ID (it starts with qsbt_).

The tracking id is public — it only lets a site report bot visits and can never read your data. You can Regenerate it at any time; the old id stops recording immediately.

Install

Send one POST https://quickseo.ai/api/track/bot per request, from your server. All installs share the same three fields:

{
  "trackingId": "qsbt_YOUR_TRACKING_ID",
  "path": "/the/requested/path",
  "userAgent": "the request's User-Agent header"
}

You can send url instead of path (QuickSEO keeps only the pathname either way), and optionally add statusCode, ip, and source.

Next.js middleware

// middleware.ts
import { NextResponse } from 'next/server'
import type { NextFetchEvent, NextRequest } from 'next/server'

const TRACKING_ID = 'qsbt_YOUR_TRACKING_ID'

export function middleware(request: NextRequest, event: NextFetchEvent) {
  // Fire-and-forget: scheduled after the response, never awaited,
  // errors swallowed — tracking can never slow down or break a page.
  event.waitUntil(
    fetch('https://quickseo.ai/api/track/bot', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        trackingId: TRACKING_ID,
        path: request.nextUrl.pathname,
        userAgent: request.headers.get('user-agent') ?? '',
      }),
    }).catch(() => {})
  )
  return NextResponse.next()
}

export const config = {
  matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
}

Express / Node.js

app.use((req, res, next) => {
  fetch('https://quickseo.ai/api/track/bot', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      trackingId: 'qsbt_YOUR_TRACKING_ID',
      path: req.path,
      userAgent: req.get('user-agent') ?? '',
    }),
  }).catch(() => {})
  next() // don't wait for the tracking call
})

PHP / WordPress

In a theme's functions.php or a small plugin — blocking => false makes the call non-blocking:

add_action('template_redirect', function () {
  wp_remote_post('https://quickseo.ai/api/track/bot', [
    'blocking' => false,
    'headers'  => ['Content-Type' => 'application/json'],
    'body'     => wp_json_encode([
      'trackingId' => 'qsbt_YOUR_TRACKING_ID',
      'path'       => $_SERVER['REQUEST_URI'] ?? '/',
      'userAgent'  => $_SERVER['HTTP_USER_AGENT'] ?? '',
    ]),
  ]);
});

curl (test it)

curl -i -X POST https://quickseo.ai/api/track/bot \
  -H 'Content-Type: application/json' \
  -d '{
    "trackingId": "qsbt_YOUR_TRACKING_ID",
    "path": "/test",
    "userAgent": "Mozilla/5.0 (compatible; GPTBot/1.2; +https://openai.com/gptbot)"
  }'

A 204 means the hit was recorded. Send a normal browser user agent instead and you'll get a 202 with {"tracked": false} — acknowledged, not stored.

Responses

StatusMeaning
204Recorded — the user agent matched a known AI crawler
202Not a known AI crawler — acknowledged, not stored
400Invalid payload
404Unknown (or rotated/disabled) tracking id
429Rate limited — the site already has 300 recorded hits in the last 60 seconds

Where the data shows up

  • The AI Traffic card on your site dashboard — top crawlers, tabbed by category.
  • The dedicated AI Traffic page — visits over time by category, all crawlers, top crawled pages.
  • Click any crawler to see its daily trend and the exact pages it read.

Viewing AI traffic data requires a paid plan. Ingestion works on any plan, so hits recorded before an upgrade are already there when you unlock the reports.

Notes

  • It never blocks a page. Every snippet above is fire-and-forget: the tracking call runs after (or alongside) your response and its failures are swallowed. If QuickSEO is unreachable, your site doesn't notice.
  • Unknown user agents are not stored. Requests from browsers, or from bots not in the registry, answer 202 and write nothing — no visitor analytics, no personal browsing data.
  • Regenerating the tracking id invalidates the old one immediately. Snippets still sending the old id get a 404 and nothing is recorded until they're updated.
  • Bots that skip your server can't be counted. A crawler that reads a cached copy (or never requests the page) leaves no request to track — counts are what your server actually saw.
  • Raw hits are kept for 365 days.

Need a hand? Email support@quickseo.ai.