Skip to main content
Back to Guides
Setup5 min read

Cookie Consent on AMP Pages: amp-consent Explained

AMP won't run your normal CMP script. Consent on AMP goes through one component, amp-consent, plus a data-block-on-consent attribute on every tag you need to hold. Here's how the pieces fit together in 2026.

Where AMP sits in 2026

Start with an honest status check. AMP is no longer a ranking requirement. Google's page experience update in 2021 removed the rule that only AMP pages could appear in the Top Stories carousel, and traffic that once forced publishers onto AMP has drained since. But AMP is still deployed, in news, in ad-supported publishing, and through the WordPress AMP plugin, so plenty of teams still ship AMP variants and have to make consent work on them.

The thing to understand is that AMP is a sandbox. It won't run arbitrary third-party JavaScript, which is exactly what most CMP snippets are. Dropping your standard consent script onto an AMP page does nothing. AMP has its own consent component, and everything routes through it.

amp-consent: the one component

The <amp-consent> component manages the consent UI and blocks other components until consent is resolved. You configure it to talk to a CMP (many consent vendors ship an AMP integration) or to your own checkConsentHref endpoint that returns whether a prompt is needed. AMP reads and passes the IAB frameworks it supports, including TCF v2.2, the US Privacy string, and the Global Privacy Platform string, when a CMP provides them, as documented in the amp-consent reference.

data-block-on-consent: the actual gate

Declaring amp-consent doesn't hold your tags by itself. You block each one. Add the data-block-on-consent attribute to every <amp-analytics> and <amp-ad> element, and AMP delays that component's behavior (sending an analytics ping, loading an ad) until the consent instance is accepted:

<amp-analytics type="gtag" data-block-on-consent>
  <!-- config -->
</amp-analytics>

This is the AMP equivalent of script blocking on a normal page. No attribute, no block: an amp-analytics tag without data-block-on-consent will fire regardless of what the visitor chose. Audit every measurement and ad component on the page and confirm each one carries the attribute.

amp-geo: only prompt where you must

You usually don't want to show the same prompt worldwide. The <amp-geo> component detects the visitor's region on the client, and the geoOverride setting inside amp-consent lets you require the consent flow only for the regions you name, the EEA for GDPR and TCF, or California for US Privacy, for example. That keeps the prompt off pages served to regions that don't require it while still gating tags where the law applies. The configuration lives in the same amp.dev documentation as the component itself.

A minimal amp-consent setup

The component is configured with a JSON script block. A self-managed setup points AMP at your own endpoint:

<amp-consent id="consent" layout="nodisplay">
  <script type="application/json">{
    "consentInstanceId": "my-consent",
    "consentRequired": "remote",
    "checkConsentHref": "https://example.com/api/consent",
    "promptUI": "consent-ui"
  }</script>
</amp-consent>

With consentRequired set to remote, AMP calls your checkConsentHref endpoint, which returns JSON telling AMP whether a prompt is needed (for example {"consentRequired": true}). The promptUI value points at the element holding your accept and reject buttons. Combine it with an amp-geo block so the endpoint is only consulted where the law requires it. It's more moving parts than a single script tag, and that's the price of AMP's sandbox.

Don't forget withdrawal. amp-consent supports a postPromptUI, a persistent element (usually a small "manage consent" link) that lets a visitor reopen the prompt and change their mind after the first decision. Withdrawing consent has to be as easy as granting it, so wire that element up rather than leaving the choice locked after the first tap.

The limitation you have to plan around

AMP stores a single common consent status. It reads and forwards TCF, US Privacy, and GPP strings, but on the page itself a visitor gets one accept-or-reject decision; AMP does not let a user turn individual vendors or purposes on and off the way a full TCF CMP does. If your monetization depends on granular per-purpose TCF signaling, AMP is a compromise, and you should know that going in. Our guides to the Transparency and Consent Framework and TCF 2.2 for publishers explain what granularity you're trading away.

One more thing: your AMP page and your canonical HTML page are two surfaces. A visitor may land on either, and a search or social referral often serves the AMP variant. Keep the categories and the vendor list consistent between them so consent means the same thing on both.

Test that the block actually happened

AMP's consent behavior is easy to misconfigure and hard to eyeball, so verify it the way you'd verify script blocking anywhere. Load the AMP page in a fresh session with the network panel open, and confirm no analytics ping and no ad request fires before you accept. Then accept, and watch those same requests appear. If a ping shows up before your choice, the component is missing data-block-on-consent, or the consent instance resolved as not-required for your region. One more thing that trips people up: AMP pages are often served from Google's AMP cache on a Google domain rather than your own, which changes the origin your endpoint sees, so test the cached version too, not merely the copy on your server.

Practical takeaways

  1. Don't try to run a standard JS CMP on AMP. Use amp-consent, and check whether your consent vendor ships an AMP integration.
  2. Put data-block-on-consent on every amp-analytics and amp-ad element, and verify none was missed.
  3. Use amp-geo and geoOverride to prompt only in regions that require it.
  4. Accept the single-status limitation, or reconsider AMP if you need granular TCF.
  5. Keep your AMP and canonical pages aligned on categories and vendors.

On your canonical, non-AMP pages, a CMP like CookieBeam handles consent the normal way, and its scanner can be pointed at both your canonical and AMP URLs so you can confirm each surface blocks the right tags. On the AMP variant itself, the consent contract is amp-consent plus data-block-on-consent, and that's the part only AMP's own components can enforce.

AMP Cookie Consent: amp-consent & data-block-on-consent | CookieBeam | CookieBeam