Netlify Integration
Track AI crawler visits on Netlify — a zero-code Log Drain on Enterprise, or a small Edge Function on any plan.
Both options power AI Impressions; to also track Clicks, add the client-side tracking script from Site Settings → Tracking Script. Send all traffic — Airefs classifies bots versus humans and drops assets and errors server-side.
Your access token is in your Airefs account under Site Settings → Access Token.
Option A: Log Drain (Enterprise)
Recommended on Enterprise: no code, and it sees every request including CDN-cached responses.
- In the Netlify dashboard, go to Logs → Log Drains and enable the General HTTP endpoint drain.
- Endpoint URL:
https://api.getairefs.com/v1/logs/netlify- Authorization header value — the
Bearerprefix is required:
Bearer YOUR_ACCESS_TOKEN- Format: NDJSON (JSON also works).
- Log types: enable Traffic logs only; disable Function, Edge function, Deploy, and WAF logs.
- Leave the personally identifiable information exclusion off — it strips
user_agentandclient_ip, which Airefs needs for AI crawler detection. - Click Connect.
Option B: Edge Function (any plan)
- Save this file as
netlify/edge-functions/airefs.tsin your repository:
declare const Netlify: {
env: { get(name: string): string | undefined };
};
interface EdgeContext {
next(): Promise<Response>;
waitUntil(promise: Promise<unknown>): void;
ip: string;
requestId?: string;
geo?: { country?: { code?: string } };
}
const AIREFS_LOG_ENDPOINT = "https://api.getairefs.com/v1/logs/http";
async function forwardLogRecord(
request: Request,
response: Response,
context: EdgeContext,
): Promise<void> {
const accessToken = Netlify.env.get("AIREFS_ACCESS_TOKEN");
if (!accessToken) {
return;
}
// Netlify does not add request headers; the stable request id lives on the
// context object and makes retried deliveries idempotent.
const url = new URL(request.url);
const record = {
event_id: context.requestId || undefined,
timestamp: new Date().toISOString(),
status_code: response.status,
request_method: request.method,
request_path: url.pathname,
query_string: url.search.slice(1) || undefined,
hostname: url.hostname,
content_type: response.headers.get("content-type")?.split(";")[0] ?? undefined,
client_ip: context.ip,
user_agent: request.headers.get("user-agent") ?? undefined,
referrer: request.headers.get("referer") ?? undefined,
country_code: context.geo?.country?.code,
event_client: "netlify-edge-function@1.0.0",
};
await fetch(AIREFS_LOG_ENDPOINT, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": accessToken,
},
body: JSON.stringify(record),
});
}
export default async (request: Request, context: EdgeContext): Promise<Response> => {
const response = await context.next();
context.waitUntil(forwardLogRecord(request, response, context).catch(() => {}));
return response;
};
export const config = {
path: "/*",
excludedPath: ["/.netlify/*"],
};- In the Netlify dashboard, add an environment variable
AIREFS_ACCESS_TOKENwith your access token. - Deploy. The function passes every request through untouched and reports it in the background with
context.waitUntil, adding no latency.
Verification
Visit a few pages on your site. Events appear in your Airefs dashboard within a few minutes.
Outside dry-run mode, a successful response means Airefs stored every accepted record and reports why the rest were dropped. For a one-off test before going live, POST a sample record with ?dry_run=1 appended to the endpoint URL: Airefs returns a per-record verdict, including the bot classification it detected, without storing anything.
Log Drain returning a validation error with status 400? The Authorization value is almost certainly missing the Bearer prefix. Edge Function deployed but no events? Confirm the AIREFS_ACCESS_TOKEN environment variable is set. Need help? Email support@getairefs.com.
