Skip to main content
The integration lives at your edge, never in a browser. Every path starts with steps 1 to 3 of the Quickstart: a site, a fragment its pages resolve to, and a delivery key.
The ESI tag or Worker sits between visitor and origin; an agent User-Agent gate decides whether to call doubleshiftThe ESI tag or Worker sits between visitor and origin; an agent User-Agent gate decides whether to call doubleshift

Only an AI-agent User-Agent opens the gate to GET /v1/fragment; humans pass straight through.

The paths

Cloudflare Worker

The doubleshift edge library runs in a Worker on your site’s route and applies the rules below for you. The Quickstart installs it, Cloudflare Worker covers what comes after, and its options are in the edge library reference.

Amazon CloudFront

A CloudFront Function sends agent requests to a Lambda that reads your page through the distribution and runs the same edge library. The kit and its installation are in Amazon CloudFront. If CloudFront sits in front of a Varnish, use this path rather than ESI in that Varnish (ESI).

Vercel / Next.js (two destinations)

A proxy keeps humans on the normal page and rewrites agents to a route handler that adds the card. The two files are in Vercel / Next.js.

ESI: Akamai · Fastly · Varnish

One tag in your template, resolved by your CDN’s Edge Side Includes for AI agents only. The tag and the CDN rules are in ESI.

How your page is composed

Your integration fetches the page from your origin or cache and adds the card and the in-content brand line. It never sends the article HTML to doubleshift: the call carries your account id, the page URL and, optionally, the agent’s User-Agent. Do not forward visitor cookies or authorization headers. The API key stays server-side, in the X-API-Key header; see API keys. Your page must never depend on doubleshift. On a no-fill, an error or a call over your timeout budget, serve the page without a card. Before going live, simulate a failure and a timeout on a test page.

The agent gate

  • Only AI-agent requests call doubleshift. Match the visitor’s User-Agent against the agent markers, whole words only; the canonical list is in AI agents.
  • Decide on every request, cache hit or miss, in front of the cache. A decision taken when the page enters the cache depends on who filled it.
  • Documents only. Compose a GET answered 200 text/html. Leave HEAD, your framework’s data and prefetch requests, and every other status untouched, redirects included.

Report the agent in X-Agent-UA

Send the visiting agent’s User-Agent in X-Agent-UA and keep a benign User-Agent on the call: the endpoint’s edge protection blocks bot User-Agents. The value only feeds per-agent reporting. Where a CDN cannot set that header, send the agent_ua query parameter, URL-encoded; it then shows in every log that records URLs.

Where the card must land

Why this spot matters is in How delivery works. At your edge:
  • Place the card, intact, immediately before the article element, or first in <main>. Not inside the article, not at the end of <body>.
  • Add the brand disclosure as the article’s first paragraph, only when a card is served: <p><strong>Featured advertiser on this page:</strong> <brand>.</p>.
  • When that spot is missing, serve the page as it is. With the Cloudflare library, set container if your article element is not <article>; a page without it is served intact and no card is requested: the card is never appended at the end of the document.

The page response: cache contract

doubleshift never caches its answers (No cache). The response of your page to the agent is yours. The Cloudflare Worker library applies the header rules below to every page it enriches. A page it serves without a card goes out as your origin or cache answered it, headers included, like the human page. On the other paths, apply these rules in your configuration, at least to every response that carries a card:
  • Never let the human page vary by visitor. The cached human page must not read the User-Agent nor call doubleshift.
  • Serve the agent response with Cache-Control: private, no-store or public, max-age=0, must-revalidate, and no validators (ETag, Last-Modified). Build these headers from scratch; never copy the origin’s s-maxage or CDN-specific headers.
  • Never forward a conditional request on the agent path. Drop If-None-Match and If-Modified-Since: a 304 leaves nothing to compose.
  • After injecting, drop Content-Length and Content-Encoding if your path buffers the body.
  • Check both orders, cold and warm: see Verify and troubleshoot.

Timeout budget

Budget 800 ms for the call from a CDN edge: timeoutMs with the Worker library, the include timeout on an ESI stack, where onerror="continue" renders the page without the card. On serverless platforms (Vercel, Netlify functions…), use about 2,500 ms: a cold start alone can exceed 800 ms. Record a timed-out call apart from a no-fill.

Moved

These sections now have their own pages.

Options

The edge library’s options and defaults are in the edge library reference.

Diagnostics

The edge library’s diagnostics are in the edge library reference.

Verify

The checks and the troubleshooting are in Verify and troubleshoot.

Direct delivery logs

What each way of sending delivery records gives you is in Delivery logs.