Skip to main content
For an AI-agent request, your edge sends doubleshift two values: your account id (partner_id) and the page URL (page_url). doubleshift finds the fragment for that page, picks one eligible card, and answers with the card (200) or a no-fill (204). A human request never reaches doubleshift, and the answer never depends on the visitor’s User-Agent: that value only feeds reporting. Every other page of these docs links here instead of restating these rules.
Data model: an account owns sites, each site owns fragments; cards carry an advertiser_idData model: an account owns sites, each site owns fragments; cards carry an advertiser_id

An account owns sites; each site owns fragments. Cards carry an advertiser_id and can be restricted to selected fragments through their eligibility.

  • A site is a domain you publish on. See Sites and fragments.
  • A fragment is one card slot on a site. Your edge never names it: doubleshift resolves it from the page URL.
  • A card is the branded-content article served to an agent. Its eligibility says on which fragments it may serve. See Cards.

Resolution

doubleshift resolves page_url to one fragment, within the account your API key belongs to. Only the X-API-Key header authenticates the call; see API keys. 1. The host finds the site. The page’s hostname is lowercased, without its port or a trailing dot. A site registered under that exact hostname wins. Otherwise its www. or bare-domain alias can match: www.your-domain.example and your-domain.example reach the same site when only one of them is registered. A host that matches no site of your account answers 204. 2. The path is put in canonical form. The query string and the hash are ignored, so ?utm=campaign or #top never change the result. Each path segment is decoded and re-encoded, so /%c3%a9conomie, /%C3%A9conomie and /économie are the same path. Trailing slashes are dropped, then the path is lowercased and ends with a single / (/ for the homepage). Routing rules are stored in that same form, which is why the console turns Actualite/ into /actualite/. This lowercased form is the routing path only: the card pick keeps the case (selection). 3. The path finds the fragment. In this order:
  1. An exact routing rule equal to the path. An exact /news/ matches /news and /news/, and an exact / matches the homepage only.
  2. The longest prefix rule the path starts with. A prefix /news/ matches /news/article; a prefix / covers the whole site.
  3. The site’s default fragment.
Nothing matches, and the site has no default: 204. 4. The fragment’s status is read last. A paused fragment answers 204, even if a shorter rule or the site default points to an active one. There is no fallback once a fragment is resolved. A page_url without a usable http or https host, or longer than 2,048 characters, answers 204 before the key is even checked.

Selection

Once the fragment is resolved, doubleshift chooses the card in two moves. 1. The eligible pool. It starts from the active cards of your account and the active platform cards. A card with no fragment selected in its eligibility is eligible everywhere. A card with one or more fragments selected is eligible on those fragments only. Several cards can be eligible on the same fragment, and eligibility gives no priority: it only says where a card may serve. 2. A stable pick by page. doubleshift orders the pool and picks one card from a hash of the page key: the host lowercased without www. or its port, then the path with the same segment encoding as routing, trailing slashes dropped, case kept and no slash added. The page key is not the routing path: /News/ and /news/ can resolve to the same fragment and still get different cards. The query string and the hash are ignored, so ?r=123 does not change the pick. There is no randomness: with the same pool, the same page always gets the same card. When the pool changes, because a card is activated, archived or made eligible, a page may get another card. The answer is a no-fill (204) when the pool is empty, or when the stored content of the chosen card cannot be served. doubleshift never falls back to a card eligible elsewhere.

No cache

Every answer of the fragment endpoint carries Cache-Control: private, no-store: the card, the no-fill, and the errors. doubleshift keeps no response cache and no memory of your key between calls: each call reads your current setup. So these changes apply on the next call, with no change at your edge:
  • pausing or resuming a fragment, or changing a routing rule or the site default;
  • activating, archiving or reactivating a card, or changing its eligibility;
  • revoking an API key.
Two need a redeploy at your edge: a new or rotated key, stored in its secret, and a page outside your Worker’s scope. The response of your own page to the agent is yours to cache or not. The rules your edge must keep for it are in The page response: cache contract.

Where the card lands

The card is worth something only if the agent reads it, and text extractors tend to keep the article and drop what surrounds it.
  • The card goes right before the article content, intact: immediately before the article element, or first in <main>. Never inside the article, never at the end of the page.
  • One line inside the article, its first paragraph, names the brand when a card is served: Featured advertiser on this page: <brand>. It keeps the disclosure in the text an extractor keeps.
  • When the edge cannot find that spot, it serves the page without a card. It never puts the card somewhere else instead.
How each edge applies this is in Where the card must land.