---
title: "Cloudflare Integration"
description: "Track AI crawler visits on any site behind Cloudflare — with a lightweight Worker on any plan, or zero-code Logpush on Enterprise."
---

> Documentation Index
> Fetch the complete documentation index at: /llms.txt
> Use this file to discover all available pages before exploring further.

# Cloudflare Integration

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](/docs/impressions/); to also track [Clicks](/docs/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.

1.  In the Cloudflare dashboard, go to **Workers & Pages → Create** and create a Worker from the Hello World template.
2.  Replace the generated code with:

```js
// @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;
  },
};
```

3.  Deploy, then open the Worker’s **Settings → Variables and Secrets** and add a secret named `AIREFS_ACCESS_TOKEN` with your access token.
4.  Add a route so the Worker runs on your domain: **your zone → Workers Routes → Add route**, pattern `yourdomain.com/*`, select the Worker.
5.  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.

1.  In your zone, go to **Analytics & Logs → Logpush** and create a job with the **HTTP destination** type.
2.  Set the destination URL (the header is URL-encoded into it):

```text
https://api.getairefs.com/v1/logs/cloudflare?header_Authorization=Bearer%20YOUR_ACCESS_TOKEN
```

3.  Dataset: **HTTP requests**. Choose **Filtered logs** and filter `ClientRequestHost` equals your domain.
4.  Select these fields: `ClientIP`, `ClientRequestHost`, `ClientRequestMethod`, `ClientRequestReferer`, `ClientRequestScheme`, `ClientRequestURI`, `ClientRequestUserAgent`, `RayID`, `EdgeStartTimestamp`, `EdgeResponseStatus`, `EdgeResponseContentType`, `ClientCountry`.

5.  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](mailto:support@getairefs.com).

Source: /docs/integrations/cloudflare/
