Node.js Integration
Track bot and AI crawler visits from any Node.js application. Works with Express, Fastify, Next.js, Koa, and any Node.js HTTP server.
Time to set up: ~2 minutes
Prerequisites
- A Node.js application (v18+ for native fetch)
- A BotSights account with a project created for your domain
- Your API Key (found in BotSights → Account → Projects → API Key)
Express / Connect
Add the middleware to your Express app:
const BOTSIGHTS_API_KEY = 'YOUR_API_KEY_HERE';
const BOTSIGHTS_API_URL = 'https://www.botsights.com/api/log';
const SKIP_EXT = new Set([
'css','js','png','jpg','jpeg','gif','svg','webp','avif',
'ico','woff','woff2','ttf','eot','map','mp4','webm','mp3',
]);
function botsights(req, res, next) {
const startTime = Date.now();
const ext = req.path.split('.').pop();
if (ext && SKIP_EXT.has(ext.toLowerCase())) return next();
const originalEnd = res.end;
res.end = function (...args) {
originalEnd.apply(res, args);
fetch(BOTSIGHTS_API_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
api_key: BOTSIGHTS_API_KEY,
ua: req.headers['user-agent'] || '',
url: req.originalUrl || req.url,
ip: req.headers['cf-connecting-ip']
|| req.headers['x-forwarded-for']?.split(',')[0]?.trim()
|| req.socket?.remoteAddress || '',
referer: req.headers['referer'] || '',
status_code: res.statusCode,
duration_ms: Date.now() - startTime,
content_type: res.getHeader?.('content-type') || '',
http_method: req.method,
source: 'nodejs',
}),
}).catch(() => {});
};
next();
}
// Use it:
app.use(botsights);Next.js (Middleware)
For Next.js apps not hosted on Cloudflare, add to middleware.ts:
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
const BOTSIGHTS_API_KEY = 'YOUR_API_KEY_HERE';
const BOTSIGHTS_API_URL = 'https://www.botsights.com/api/log';
export function middleware(request: NextRequest) {
const response = NextResponse.next();
const startTime = Date.now();
// Skip static assets
const ext = request.nextUrl.pathname.split('.').pop() || '';
const skip = ['css','js','png','jpg','svg','ico','woff','woff2'];
if (skip.includes(ext)) return response;
// Send analytics after response (non-blocking via waitUntil if available)
const data = {
api_key: BOTSIGHTS_API_KEY,
ua: request.headers.get('user-agent') || '',
url: request.nextUrl.pathname + request.nextUrl.search,
ip: request.headers.get('x-forwarded-for')?.split(',')[0] || '',
referer: request.headers.get('referer') || '',
http_method: request.method,
source: 'nodejs_nextjs',
};
fetch(BOTSIGHTS_API_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
}).catch(() => {});
return response;
}
export const config = {
matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
};How It Works
The middleware intercepts every incoming request, measures the response time, and sends analytics to BotSights after the response is sent. Static assets are automatically skipped.
- Non-blocking — analytics are sent after
res.end(), no impact on response time - Server-side — captures all visitors including bots that don't execute JavaScript
- No cookies — nothing stored in the visitor's browser
- No client-side code — zero JavaScript added to your pages
Troubleshooting
No data appearing?
- Check your API key is correct
- Verify your server can make outbound HTTPS requests
- Check that the domain in your BotSights project matches your site's domain