guides

Analytics

Track which AI bots read your content and which actions agents invoke.

next-ai-ready provides two hooks to track AI consumer activity without adding external dependencies.

Setup

Next.js runs instrumentation.ts in both Node.js and Edge. Register hooks from a Node-only file via the `next-ai-ready/hooks` subpath (not the main package entry) so Turbopack does not pull build-time Node modules into the Edge bundle.

`instrumentation.ts`

ts
export async function register() {
  if (process.env.NEXT_RUNTIME === "nodejs") {
    await import("./instrumentation-node");
  }
}

`instrumentation-node.ts`

ts
import "server-only";
import { registerAiHooks } from "next-ai-ready/hooks";

registerAiHooks({
  onAiRequest: (info) => {
    console.log("AI request:", info.bot, info.artifact, info.path);
  },
  onInvoke: (info) => {
    console.log("Action invoked:", info.action, info.ok, info.latencyMs);
  },
});

npx next-ai-ready init scaffolds both files for you.

`onAiRequest`

Fires when an AI bot reads a Knowledge Plane artifact. The callback receives:

FieldTypeDescription
botstring?Detected bot name (e.g. "GPTBot", "ClaudeBot"). undefined if unrecognized.
pathstringRequest path (e.g. /llms.txt, /docs/intro.md).
artifactstringArtifact type: "llms-txt", "page-md", "page-ai-json", "openapi", "tools".
uastringRaw User-Agent header.
methodstringHTTP method.

Bot detection matches these user agents: GPTBot, OAI-SearchBot, ChatGPT-User, PerplexityBot, ClaudeBot, anthropic-ai, Google-Extended, CCBot, Bytespider, Applebot-Extended.

`onInvoke`

Fires when an action is called via HTTP or MCP. The callback receives:

FieldTypeDescription
actionstringAction name (e.g. "search_products").
okbooleanWhether the invocation succeeded.
latencyMsnumberHandler execution time in milliseconds.
errorstring?Error message if ok is false.
callerstring?"http" or "mcp".

Example: sending to an analytics service

Put your SDK calls in instrumentation-node.ts:

ts
import "server-only";
import { registerAiHooks } from "next-ai-ready/hooks";

registerAiHooks({
  onAiRequest: (info) => {
    analytics.track("ai_request", {
      bot: info.bot,
      artifact: info.artifact,
      path: info.path,
    });
  },
  onInvoke: (info) => {
    analytics.track("ai_invoke", {
      action: info.action,
      ok: info.ok,
      latencyMs: info.latencyMs,
      caller: info.caller,
    });
  },
});

How hooks are wired

The hooks are registered globally and called by the route handlers at request time. They run synchronously in the handler's execution context — if a hook throws, the request still completes normally (the error is swallowed).

No external dependencies are required. The hooks are designed to be a thin integration point — bring your own analytics SDK.