Cloudflare Integration
Track AI crawler visits on any site behind Cloudflare — with a lightweight Worker on any plan, or zero-code Logpush on Enterprise.
Both options capture every request at the Cloudflare edge and forward it to Airefs, where bot traffic is classified and assets and errors are dropped server-side. They power AI Impressions; to also track Clicks, add the client-side tracking script from Site Settings → Tracking Script.
Your access token is in your Airefs account under Site Settings → Access Token.
Option A: Cloudflare Worker (any plan)
A passthrough Worker that returns your pages untouched and reports each request to Airefs in the background with ctx.waitUntil — it adds no latency for visitors or crawlers.
- In the Cloudflare dashboard, go to Workers & Pages → Create and create a Worker from the Hello World template.
- Replace the generated code with:
// @ts-check
/**
* @typedef {{ AIREFS_ACCESS_TOKEN: string }} Env
* @typedef {Request & { cf?: { country?: string } }} WorkerRequest
* @typedef {{ waitUntil(promise: Promise<unknown>): void }} ExecutionContext
*/
const AIREFS_LOG_ENDPOINT = "https://api.getairefs.com/v1/logs/http";
/**
* @param {WorkerRequest} request
* @param {Response} response
* @param {Env} env
*/
async function forwardLogRecord(request, response, env) {
const eventId = request.headers.get("cf-ray");
if (!eventId) {
return;
}
const url = new URL(request.url);
const record = {
event_id: eventId,
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: request.headers.get("cf-connecting-ip") ?? undefined,
user_agent: request.headers.get("user-agent") ?? undefined,
referrer: request.headers.get("referer") ?? undefined,
country_code: request.cf?.country,
event_client: "cloudflare-worker@1.0.0",
};
await fetch(AIREFS_LOG_ENDPOINT, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": env.AIREFS_ACCESS_TOKEN,
},
body: JSON.stringify(record),
});
}
export default {
/**
* @param {WorkerRequest} request
* @param {Env} env
* @param {ExecutionContext} ctx
*/
async fetch(request, env, ctx) {
const response = await fetch(request);
ctx.waitUntil(forwardLogRecord(request, response, env).catch(() => {}));
return response;
},
};- Deploy, then open the Worker’s Settings → Variables and Secrets and add a secret named
AIREFS_ACCESS_TOKENwith your access token. - Add a route so the Worker runs on your domain: your zone → Workers Routes → Add route, pattern
yourdomain.com/*, select the Worker. - Make sure the DNS record for your domain is Proxied (orange cloud) — Workers only run on proxied traffic.
Do not pre-filter anything in the Worker: send all traffic so Airefs can classify bots versus humans and drop assets and error responses server-side.
Option B: Logpush (Enterprise)
On a Cloudflare Enterprise zone, Logpush streams HTTP request logs to Airefs with no code at all.
- In your zone, go to Analytics & Logs → Logpush and create a job with the HTTP destination type.
- Set the destination URL (the header is URL-encoded into it):
https://api.getairefs.com/v1/logs/cloudflare?header_Authorization=Bearer%20YOUR_ACCESS_TOKEN- Dataset: HTTP requests. Choose Filtered logs and filter
ClientRequestHostequals your domain. Select these fields:
ClientIP,ClientRequestHost,ClientRequestMethod,ClientRequestReferer,ClientRequestScheme,ClientRequestURI,ClientRequestUserAgent,RayID,EdgeStartTimestamp,EdgeResponseStatus,EdgeResponseContentType,ClientCountry.- Create the job. Cloudflare validates the destination with a test upload; a wrong token makes validation fail with a
401.
Verification
Visit a few pages on your site. Events appear in your Airefs dashboard within a few minutes (Logpush batches roughly once per minute).
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.
No events? For the Worker: confirm the route pattern matches your domain, the DNS record is proxied, and the AIREFS_ACCESS_TOKEN secret is set. For Logpush: check the destination URL is exactly as shown with Bearer%20 URL-encoded. Need help? Email support@getairefs.com.
