{"_id":"@didyouseo/bot-traffic","name":"@didyouseo/bot-traffic","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@didyouseo/bot-traffic","version":"0.1.0","publishConfig":{"access":"public"},"description":"See which AI assistants and crawlers (ChatGPT, Claude, Perplexity, Googlebot...) visit your site. Server-side bot traffic tracking for DidYouSEO.","license":"MIT","homepage":"https://didyouseo.com/dashboard/bot-traffic","type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./next":{"types":"./dist/next.d.ts","import":"./dist/next.js","require":"./dist/next.cjs"},"./express":{"types":"./dist/express.d.ts","import":"./dist/express.js","require":"./dist/express.cjs"}},"sideEffects":false,"scripts":{"build":"tsup src/index.ts src/next.ts src/express.ts --format esm,cjs --dts --clean","test":"npm run build && node --test \"test/*.test.mjs\""},"engines":{"node":">=18"},"keywords":["bot-traffic","ai-crawlers","gptbot","claudebot","perplexitybot","googlebot","seo","geo","analytics","didyouseo"],"devDependencies":{"tsup":"^8.0.0","typescript":"^5.4.0"},"_id":"@didyouseo/bot-traffic@0.1.0","_nodeVersion":"22.15.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-+/qFqJ2Otwpm7MSV7kZCs4UMjNwzanLCSArAmzj51AQixSY9uyPV3tg4LXsEVnxmJNEQ8smGumChwns/zv+q6w==","shasum":"dabd87af38c4344604f26ec4020d23f968617a8e","tarball":"https://registry.npmjs.org/@didyouseo/bot-traffic/-/bot-traffic-0.1.0.tgz","fileCount":15,"unpackedSize":33838,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCki/w7ACT5TXZN00on1Beq9nsLI6ctYr1TPqzGjuOf4QIgY8JCvTcMluJZA8zb/xp/C2K6hF4Tcqp7qBbu9RtLYjU="}]},"_npmUser":{"name":"sathish27","email":"sathi.viper@gmail.com"},"directories":{},"maintainers":[{"name":"sathish27","email":"sathi.viper@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/bot-traffic_0.1.0_1784031256829_0.49573431815487545"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-14T12:14:16.645Z","0.1.0":"2026-07-14T12:14:17.012Z","modified":"2026-07-14T12:14:17.213Z"},"maintainers":[{"name":"sathish27","email":"sathi.viper@gmail.com"}],"description":"See which AI assistants and crawlers (ChatGPT, Claude, Perplexity, Googlebot...) visit your site. Server-side bot traffic tracking for DidYouSEO.","homepage":"https://didyouseo.com/dashboard/bot-traffic","keywords":["bot-traffic","ai-crawlers","gptbot","claudebot","perplexitybot","googlebot","seo","geo","analytics","didyouseo"],"license":"MIT","readme":"# @didyouseo/bot-traffic\n\nSee which AI assistants and crawlers — ChatGPT, Claude, Perplexity, Googlebot and ~30 more — visit your site and which pages they read.\n\nAI crawlers don't run JavaScript, so client-side analytics (GA4, Plausible, etc.) never see them. This package runs on your **server**: it spots bot-looking requests and forwards them to [DidYouSEO](https://didyouseo.com), where the bot is classified (AI answers, AI search, AI training, search indexing, SEO tools, link previews) and its IP is verified via reverse DNS to catch impostors. Classification happens server-side, so crawler lists stay current without upgrading this package. Your report lives in the DidYouSEO dashboard under **Track → Bot Traffic**.\n\n- Zero dependencies; works on Node 18+, Vercel Edge, Cloudflare Workers/Pages\n- Never blocks or slows a page: reports are non-blocking with a 2s timeout, and all errors are swallowed\n- Skips static assets and API routes locally — but keeps crawler-facing files (`robots.txt`, `llms.txt`, `llms-full.txt`, sitemap XMLs, `.md` content) trackable, since AI crawlers request those first\n- Human traffic is never stored — non-bot requests forwarded by the liberal pre-filter are discarded server-side\n- Optional status-code capture: crawlers repeatedly requesting a 404 page is a content signal — a page users and agents expect to exist\n\n## Setup\n\n1. Sign in at [didyouseo.com](https://didyouseo.com) and open **Dashboard → Track → Bot Traffic** to get your site's tracking token.\n2. `npm install @didyouseo/bot-traffic`\n3. Add one tracking call in your backend (examples below), deploy, and watch the dashboard.\n\n## Next.js (Vercel or self-hosted)\n\nAdd one line to your `middleware.ts` (or `proxy.ts` in newer Next.js):\n\n```ts\n// middleware.ts\nimport { NextResponse, type NextFetchEvent, type NextRequest } from \"next/server\";\nimport { trackBotVisit } from \"@didyouseo/bot-traffic\";\n\nexport function middleware(request: NextRequest, event: NextFetchEvent) {\n  trackBotVisit(request, event, { token: process.env.DIDYOUSEO_TOKEN! });\n\n  return NextResponse.next(); // or the rest of your existing middleware\n}\n\nexport const config = {\n  // Keep robots.txt, llms.txt, and sitemap files reachable by this middleware —\n  // AI crawlers request those before crawling the rest of your site.\n  matcher: [\"/((?!_next/static|_next/image|favicon.ico).*)\"],\n};\n```\n\nPass `event` so the report runs in the background via `waitUntil` — call it, then return your response; no `await` needed. If you have no middleware yet and want zero wiring, `withBotTraffic` from `@didyouseo/bot-traffic/next` creates one for you.\n\n## Cloudflare Pages\n\n```ts\n// functions/_middleware.ts\nimport { trackBotVisit } from \"@didyouseo/bot-traffic\";\n\nexport async function onRequest(context) {\n  trackBotVisit(context.request, context, { token: \"YOUR_TRACKING_TOKEN\" });\n  return context.next();\n}\n```\n\n## Cloudflare Workers\n\nWorkers see the final response, so use the response-aware variant to capture status codes:\n\n```ts\nimport { trackBotResponse } from \"@didyouseo/bot-traffic\";\n\nexport default {\n  async fetch(request: Request, env: Env, ctx: ExecutionContext) {\n    const response = await handleRequest(request);\n    trackBotResponse(request, response, ctx, { token: env.DIDYOUSEO_TOKEN });\n    return response;\n  },\n};\n```\n\n## Express / Connect\n\n```ts\nimport { botTraffic } from \"@didyouseo/bot-traffic/express\";\n\napp.use(botTraffic({ token: process.env.DIDYOUSEO_TOKEN! }));\n```\n\nCalls `next()` immediately and sends the report from the response's `finish` listener — status code included, zero added latency.\n\n## Hono\n\n```ts\nimport { trackBotResponse } from \"@didyouseo/bot-traffic\";\n\napp.use(\"*\", async (c, next) => {\n  await next();\n  trackBotResponse(c.req.raw, c.res, c.executionCtx, { token: \"YOUR_TRACKING_TOKEN\" });\n});\n```\n\n## Any other server\n\nIf you have a Fetch-API `Request`, use `trackBotVisit(request, contextOrNull, options)` — await the result if your runtime has no `waitUntil`. Otherwise build the payload yourself:\n\n```ts\nimport { reportBotVisit } from \"@didyouseo/bot-traffic\";\n\nawait reportBotVisit(\n  { path: \"/pricing\", userAgent: req.headers[\"user-agent\"], ip: clientIp, status: 200 },\n  { token: process.env.DIDYOUSEO_TOKEN! }\n);\n```\n\nOr skip the package and POST the JSON directly:\n\n```\nPOST https://didyouseo.com/api/bot-traffic\nContent-Type: application/json\n\n{ \"token\": \"...\", \"path\": \"/pricing\", \"userAgent\": \"GPTBot/1.2\", \"ip\": \"203.0.113.7\", \"status\": 200 }\n```\n\n## Options\n\n| Option | Default | What it does |\n|---|---|---|\n| `token` | — (required) | Your site's tracking token from the dashboard |\n| `endpoint` | `https://didyouseo.com/api/bot-traffic` | Ingest URL override |\n| `timeoutMs` | `2000` | Max wait before the report is abandoned |\n| `filter` | `isLikelyBot` | Which user-agents to forward; return `true` to forward everything |\n| `pathFilter` | `isTrackablePath` | Which paths to forward; default skips assets/API routes but keeps crawler-facing files |\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-ff35d01a221f4c1172f86107440cd8c5"}