Skip to main content
Documentation

Capture AI crawlers on a Framer site.

Last reviewed 2026-10-19

Advanced reverse-proxy setup for sites on an eligible Framer plan using a Cloudflare Worker.

Framer has no request logs or server code, so a Cloudflare Worker in front of the site proxies requests to Framer and reports AI crawlers. This is an advanced setup for sites on a Framer plan that allows reverse proxying; it is not recommended for ordinary Framer custom domains.

You need your site ID and server secret from Settings → Connection (see Hosting integrations). In the dashboard, Connect analytics → Hosting integrations → Framer shows these steps with your site ID, domain and secret filled in. Below, replace <your-site-id>, <paste-your-server-secret> and example.com with your own values.

Set up with your coding agent

Hand the setup to Claude Code, Codex or another coding agent. Replace the site ID and example.com with your own; the agent asks you for the server secret. In the dashboard, Install with AI fills them in.

Prompt
Configure Framer so example.com sends reliable AI crawler request telemetry to Virent.

Site ID: <your-site-id>
Use the full Virent server secret from the Connect dialog. Do not use the masked preview "vha_sk_••••" as the real value.

Use the current provider documentation: https://www.framer.com/help/articles/how-to-proxy-with-cloudflare/

Steps:
1. Confirm Framer eligibility: Confirm the site is on an eligible Framer plan for reverse proxying. Keep its free Framer subdomain published; it becomes the Worker origin. This advanced method is not recommended for ordinary Framer custom domains.

2. Create the reverse-proxy Worker: Create a Cloudflare Worker with this code. Add VIRENT_INGEST_SECRET as a Worker secret and FRAMER_ORIGIN as the hostname of the free Framer subdomain, without https://.

const SITE_ID = "<your-site-id>"
const INGEST = "https://stage.virent.app/v1/ingest/bot"
const ASSET = /\.(?!(?:html?|txt|md|xml|json|pdf)$)[a-z0-9]+$/i

export default {
  async fetch(request, env, ctx) {
    const publicUrl = new URL(request.url)
    const originUrl = new URL(request.url)
    originUrl.hostname = env.FRAMER_ORIGIN

    const response = await fetch(new Request(originUrl, request))
    const userAgent = request.headers.get("user-agent") || ""

    if (!ASSET.test(publicUrl.pathname) && ["GET", "HEAD"].includes(request.method)) {
      ctx.waitUntil(fetch(INGEST, {
        method: "POST",
        headers: {
          "content-type": "application/json",
          "x-api-key": env.VIRENT_INGEST_SECRET,
        },
        body: JSON.stringify({
          siteId: SITE_ID,
          url: publicUrl.origin + publicUrl.pathname,
          host: publicUrl.host,
          path: publicUrl.pathname,
          query: {},
          method: request.method,
          statusCode: response.status,
          userAgent,
          referer: null,
          country: request.cf?.country || null,
          requestId: request.headers.get("cf-ray") || crypto.randomUUID(),
          timestamp: new Date().toISOString(),
        }),
      }).catch(() => {}))
    }

    return response
  },
}

3. Route the custom domain: Follow Framer’s Cloudflare proxy guide to create the dummy proxied DNS record, bind the Worker route for *example.com/*, and set the canonical URL in Framer.

4. Activate and verify: Activate the Worker, verify normal pages and assets still load from Framer, then send an AI crawler request and confirm it appears in Virent.

Keep the secret server-side, preserve 100% request coverage where the provider supports sampling, and verify both normal site delivery and a crawler request after activation.

Steps#

  1. Confirm Framer eligibility

    Confirm the site is on an eligible Framer plan for reverse proxying. Keep its free Framer subdomain published; it becomes the Worker origin. This advanced method is not recommended for ordinary Framer custom domains.

  2. Create the reverse-proxy Worker

    Create a Cloudflare Worker with this code. Add VIRENT_INGEST_SECRET as a Worker secret and FRAMER_ORIGIN as the hostname of the free Framer subdomain, without https://.

    worker.js
    const SITE_ID = "<your-site-id>"const INGEST = "https://stage.virent.app/v1/ingest/bot"const ASSET = /\.(?!(?:html?|txt|md|xml|json|pdf)$)[a-z0-9]+$/iexport default {  async fetch(request, env, ctx) {    const publicUrl = new URL(request.url)    const originUrl = new URL(request.url)    originUrl.hostname = env.FRAMER_ORIGIN    const response = await fetch(new Request(originUrl, request))    const userAgent = request.headers.get("user-agent") || ""    if (!ASSET.test(publicUrl.pathname) && ["GET", "HEAD"].includes(request.method)) {      ctx.waitUntil(fetch(INGEST, {        method: "POST",        headers: {          "content-type": "application/json",          "x-api-key": env.VIRENT_INGEST_SECRET,        },        body: JSON.stringify({          siteId: SITE_ID,          url: publicUrl.origin + publicUrl.pathname,          host: publicUrl.host,          path: publicUrl.pathname,          query: {},          method: request.method,          statusCode: response.status,          userAgent,          referer: null,          country: request.cf?.country || null,          requestId: request.headers.get("cf-ray") || crypto.randomUUID(),          timestamp: new Date().toISOString(),        }),      }).catch(() => {}))    }    return response  },}
  3. Route the custom domain

    Follow Framer’s Cloudflare proxy guide to create the dummy proxied DNS record, bind the Worker route for *example.com/*, and set the canonical URL in Framer.

  4. Activate and verify

    Activate the Worker, verify normal pages and assets still load from Framer, then send an AI crawler request and confirm it appears in Virent.

Check Framer's current documentation if its screens differ from these steps.

Verify#

Send a test crawler request to your site. The setup dialog in Virent shows "Virent is receiving AI crawler traffic" once the first request arrives.

On this page