VisitorType

Server-side tracking

Most AI crawlers — GPTBot, ClaudeBot, PerplexityBot, CCBot — request your HTML and leave without executing JavaScript, so a browser snippet alone can never see them. Server-side tracking closes the gap: your backend (or edge) reports every request it serves, and AI Tag Manager classifies it. Events arrive with source: server in analytics.

The endpoint

POST https://visitortype.ai/api/c/AITM-XXXXXXX/server-collect
Content-Type: application/json

{ "userAgent": "<the request's User-Agent>", "path": "/pricing", "referrer": "" }

// or batched (up to 500):
{ "events": [ { "userAgent": "...", "path": "/a" }, { "userAgent": "...", "path": "/b" } ] }
Human-classified events are not stored by this endpoint — the browser snippet already records humans, so storing them here would count every visit twice. Server-side tracking exists to catch the visitors that never run JavaScript (AI crawlers, assistants, monitors). Running server-side only, without the snippet? Add "includeHumans": true to the payload to keep human page views.

Next.js (middleware)

Copy integrations/nextjs-middleware.ts into your project. It reports via event.waitUntil, adding zero latency to responses:

export function middleware(req: NextRequest, event: NextFetchEvent) {
  event.waitUntil(
    fetch(`${VISITORTYPE_HOST}/api/c/${CONTAINER_ID}/server-collect`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        userAgent: req.headers.get("user-agent") ?? "",
        path: req.nextUrl.pathname,
        referrer: req.headers.get("referer") ?? "",
      }),
    }).catch(() => undefined)
  );
  return NextResponse.next();
}
Recent Next.js versions renamed middleware.ts to proxy.ts — the code is the same, only the filename changes.

Cloudflare Workers

integrations/cloudflare-worker.js runs in front of any origin — no code changes to the site itself. It passes requests through and reports page-like URLs via ctx.waitUntil.

Express / Node

integrations/express-middleware.jsbuffers events and ships them in batches every 5 seconds, so busy sites don't pay one outbound request per page view:

const { aitmTrack } = require("./aitm-express");
app.use(aitmTrack);

Anything else

Any environment that can send an HTTP POST works — nginx mirror, a log shipper, a cron job over access logs. Skip static assets (images, CSS, JS) and send page-like requests only.