@visitedby/edge
v0.4.0
Published
Server-side AI crawler tracking for visitedby.ai — catch GPTBot, ClaudeBot & friends that never run JavaScript
Downloads
605
Maintainers
Readme
@visitedby/edge
Server-side AI crawler tracking for visitedby.ai.
AI crawlers — GPTBot, ClaudeBot, PerplexityBot, Google-Extended — fetch raw HTML. They never execute the client snippet and rarely load images, so client-side analytics is structurally blind to them. This helper runs where your HTML is served and forwards only bot/agent hits to visitedby; human visitors stay with the client snippet, so nothing double-counts.
- Zero dependencies, ~1 KB, Web-standard
Request - Fire-and-forget: never throws, never delays a response (3s hard timeout)
- No new data category: just path + user-agent, same as any server log
Next.js
// middleware.ts
import { NextResponse } from 'next/server'
import { trackAgents } from '@visitedby/edge'
export function middleware(request: Request, event: { waitUntil(p: Promise<unknown>): void }) {
event.waitUntil(trackAgents(request, { key: process.env.VISITEDBY_SECRET }))
return NextResponse.next()
}
// pages only — skip assets and API routes
export const config = { matcher: ['/((?!_next|api|.*\\..*).*)'] }Cloudflare Workers / anything with fetch
import { trackAgents } from '@visitedby/edge'
export default {
async fetch(request, env, ctx) {
ctx.waitUntil(trackAgents(request, { key: process.env.VISITEDBY_SECRET }))
return handle(request)
},
}Express / Fastify / Koa / plain Node (18+)
import { trackAgentsNode } from '@visitedby/edge'
app.use((req, _res, next) => {
void trackAgentsNode(req, { key: process.env.VISITEDBY_SECRET }) // fire-and-forget
next()
})SvelteKit (src/hooks.server.ts)
import { trackAgents } from '@visitedby/edge'
export async function handle({ event, resolve }) {
void trackAgents(event.request, { key: process.env.VISITEDBY_SECRET })
return resolve(event)
}Astro (src/middleware.ts)
import { trackAgents } from '@visitedby/edge'
export function onRequest({ request }, next) {
void trackAgents(request, { key: process.env.VISITEDBY_SECRET })
return next()
}Not on a JS runtime? There's a WordPress plugin and a paste-able Cloudflare Worker that works in front of any origin.
Generate your secret ingest key (vbs_…) in the dashboard under
Settings → General → Tracking and keep it in an env var — it must never
ship to browsers (the public vb_ site key stays in your page HTML for the
snippet; server-side forwards using it are rejected once a secret exists).
Hits appear on the Traffic page (AI agents & crawlers table) within
seconds, each verified against the operator's published IP ranges.
