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`
export async function register() {
if (process.env.NEXT_RUNTIME === "nodejs") {
await import("./instrumentation-node");
}
}`instrumentation-node.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:
| Field | Type | Description |
|---|---|---|
bot | string? | Detected bot name (e.g. "GPTBot", "ClaudeBot"). undefined if unrecognized. |
path | string | Request path (e.g. /llms.txt, /docs/intro.md). |
artifact | string | Artifact type: "llms-txt", "page-md", "page-ai-json", "openapi", "tools". |
ua | string | Raw User-Agent header. |
method | string | HTTP 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:
| Field | Type | Description |
|---|---|---|
action | string | Action name (e.g. "search_products"). |
ok | boolean | Whether the invocation succeeded. |
latencyMs | number | Handler execution time in milliseconds. |
error | string? | Error message if ok is false. |
caller | string? | "http" or "mcp". |
Example: sending to an analytics service
Put your SDK calls in instrumentation-node.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.