NewWe just launched a fixed-price startup sprint: a landing page in 14 days.See sprint pricing
Share
Home/Blog/Analytics
AnalyticsJul 24, 2026·11 min read

Google Consent Mode v2 in 3 Steps (GTM, Shopify, or Plain HTML)

Most guides explain what Consent Mode is and stop there. This one shows you the exact tags, the exact order, and how to prove it works, for three different setups.

MarrelayDigital studio, Toronto

If you run ads or analytics for visitors in the EU or UK, Google now requires Consent Mode v2. Get it wrong and you quietly lose conversion data and remarketing audiences. Get it right and you keep measuring, legally, even when people decline cookies. Here is the whole thing in three steps.

What Consent Mode actually does (in one minute)

A normal cookie banner blocks Google tags entirely until someone clicks accept. That keeps you compliant, but it means everyone who declines becomes invisible: no conversions, no audiences, big gaps in your reporting.

Consent Mode changes the deal. Instead of blocking the tags, your tags still load, but they load in a restricted state. When a visitor has not consented, Google receives no cookies and no identifiers, only anonymous, aggregated pings. Google then uses modelling to estimate the conversions you could not observe directly. You stay compliant and you keep a usable picture of performance.

Version 2 added two new signals on top of the original two. That is the entire difference, and it is why so many accounts started showing warnings.

SignalControlsAdded in
analytics_storageAnalytics cookies (GA4 measurement)v1
ad_storageAdvertising cookies (conversions, remarketing)v1
ad_user_dataWhether user data may be sent to Google for adsv2
ad_personalizationWhether data may be used for personalised ads / remarketingv2
The four consent signals. The last two are what "v2" added.
PAGE LOADTIME1. Consent defaultad_storage: deniedanalytics_storage: denied2. Google tags loadRestricted modeNo cookies set3. Visitor choosesgtag(consent, update)Granted signals unlockModelling fills the gap
How a page load works with Consent Mode: defaults fire first, the banner collects a choice, then an update unlocks whatever was granted.

Step 1: Set your defaults (deny first)

Before any Google tag runs, you tell Google "assume no consent". This is the safe default and it is what regulators expect. You grant permissions later, only if the visitor agrees.

A common refinement: deny by default for EU/UK visitors, and grant by default elsewhere (if your legal advice allows implied consent in those regions). The `region` parameter does exactly that.

Place this in <head>, ABOVE your GTM or gtag snippet.
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}

  // 1) Strictest default for regions that require opt-in
  gtag('consent', 'default', {
    ad_storage: 'denied',
    ad_user_data: 'denied',
    ad_personalization: 'denied',
    analytics_storage: 'denied',
    region: ['GB','AT','BE','BG','HR','CY','CZ','DK','EE','FI','FR','DE','GR',
             'HU','IE','IT','LV','LT','LU','MT','NL','PL','PT','RO','SK','SI',
             'ES','SE','IS','LI','NO','CH'],
    wait_for_update: 500
  });

  // 2) Default for everywhere else (adjust to your legal advice)
  gtag('consent', 'default', {
    ad_storage: 'granted',
    ad_user_data: 'granted',
    ad_personalization: 'granted',
    analytics_storage: 'granted'
  });

  // Optional but recommended: helps recover conversions via URL tagging
  gtag('set', 'url_passthrough', true);
  gtag('set', 'ads_data_redaction', true);
</script>

Two settings worth understanding. `wait_for_update` tells Google to hold briefly (here 500ms) so a fast clicker does not get missed. `ads_data_redaction` strips ad identifiers while consent is denied, and `url_passthrough` passes click IDs through URLs so conversions can still be attributed without cookies.

Step 2: Update consent when the visitor chooses

When someone interacts with your banner, you send an update with what they actually agreed to. Only send the signals that changed, and only ever in response to a real choice.

Call this from your banner's Accept / Reject handlers.
// Visitor accepted everything
function consentAcceptAll() {
  gtag('consent', 'update', {
    ad_storage: 'granted',
    ad_user_data: 'granted',
    ad_personalization: 'granted',
    analytics_storage: 'granted'
  });
}

// Visitor accepted analytics only
function consentAnalyticsOnly() {
  gtag('consent', 'update', {
    analytics_storage: 'granted',
    ad_storage: 'denied',
    ad_user_data: 'denied',
    ad_personalization: 'denied'
  });
}

// Visitor rejected everything: send nothing, the deny defaults already stand.

Step 3: Wire it up in your platform

The first two steps are the same everywhere. What changes is where you paste them. Here are the three setups we see most.

A. Google Tag Manager

  1. 1
    Turn on consent supportIn GTM, open Admin then Container Settings and tick "Enable consent overview". A small shield icon now appears on the Tags list so you can see each tag's consent settings at a glance.
  2. 2
    Add the defaults before everything elseCreate a Custom HTML tag containing the Step 1 code. Set its trigger to Consent Initialisation - All Pages (not All Pages). That trigger exists specifically to run before every other tag. This is the step people skip.
  3. 3
    Fire the update from your bannerMost consent platforms (Cookiebot, CookieYes, Iubenda, Osano) have a native GTM template that handles the update for you. If you built your own banner, push a dataLayer event on click and use a Custom HTML tag with the Step 2 code, triggered by that event.
  4. 4
    Check each tag's consent settingsOpen a tag, go to Advanced Settings then Consent Settings. GA4 and Google Ads tags have built-in checks, so usually you leave them alone. For non-Google tags (Meta, LinkedIn, TikTok), set "Require additional consent" for the signals they need.

B. Shopify

  1. 1
    Prefer the native routeShopify has a Customer Privacy API and a built-in cookie banner (Settings then Customer privacy). If you use Shopify's own Google & YouTube channel, consent signals are passed for you. This is the lowest-maintenance option and the one to choose if you have no developer.
  2. 2
    If you use your own GTMAdd the Step 1 script to theme.liquid inside <head>, above the GTM snippet. Shopify themes render <head> in order, so position is everything here.
  3. 3
    Hook Shopify's banner to the updateSubscribe to Shopify's visitorConsentCollected event and call your gtag update inside it, so the two systems agree instead of fighting.
Bridging Shopify's consent banner to Consent Mode.
document.addEventListener('visitorConsentCollected', (event) => {
  const c = event.detail;
  gtag('consent', 'update', {
    analytics_storage:  c.analyticsAllowed  ? 'granted' : 'denied',
    ad_storage:         c.marketingAllowed  ? 'granted' : 'denied',
    ad_user_data:       c.marketingAllowed  ? 'granted' : 'denied',
    ad_personalization: c.marketingAllowed  ? 'granted' : 'denied'
  });
});

C. Plain HTML / custom site (WordPress, Next.js, anything)

  1. 1
    Defaults go first, literallyPaste the Step 1 block as the very first <script> in <head>. Nothing Google-related may appear above it.
  2. 2
    Then your gtag or GTM snippetImmediately after. On WordPress, plugins often inject tags high in <head>, so use a plugin that lets you control priority, or add the defaults via a hook that runs earlier.
  3. 3
    Banner calls the updateWhatever banner you use, its accept and reject handlers call the Step 2 functions. That is the entire integration.

How to prove it actually works

This is the part almost every guide omits, and it is the only part that tells you whether you succeeded. Three checks, in increasing order of confidence.

  1. Google Tag Assistant: load your site in preview, click a tag, and open the Consent tab. You should see "On page load" showing denied, then "After update" reflecting the choice you made. If the before state is unknown rather than denied, your defaults are not running early enough.
  2. Browser console: type dataLayer in the console after loading the page. The very first entries should be your consent default commands, before any config or event calls. Order in that array is the proof.
  3. GA4 DebugView and Ads diagnostics: in GA4 admin, open DebugView and confirm events still arrive when you decline (they will be cookieless). In Google Ads, the conversion diagnostics panel stops showing the consent mode warning within a few days once signals arrive correctly.

Five mistakes we fix most often

  • Defaults loading after GTM. The fix is always the Consent Initialisation trigger, never the All Pages trigger.
  • Only implementing the two v1 signals. Without ad_user_data and ad_personalization you are on v1, and Google treats that as non-compliant for EEA ads.
  • Sending an update on every page load regardless of choice. Updates should reflect a real, stored decision, not a hardcoded grant.
  • Blocking tags AND using consent mode. If your banner also physically blocks the tags, they never load, so no modelling happens and you get the worst of both worlds.
  • Forgetting non-Google tags. Meta and LinkedIn pixels are not covered by Google Consent Mode. They need their own consent gating.

Questions we get asked

Do I need this if all my customers are in the US or Canada?

Strictly, Google requires it for EEA and UK traffic. But if even a small share of your visitors come from those regions, or you ever plan to advertise there, implementing it now costs an hour and prevents your audiences being disabled later. It also future-proofs you as North American privacy laws tighten.

Will I lose data?

You lose some observed data from people who decline, which you were losing anyway with a blocking banner. What you gain is modelled conversions filling much of that gap, plus continued visibility that you would otherwise not have at all.

Is basic or advanced mode better?

Basic blocks tags until consent. Advanced loads them in a restricted state and enables modelling. Advanced gives materially better data recovery, which is why almost everything above describes advanced. Choose basic only if your legal position requires zero pings before consent.

Does a consent platform do all this for me?

Mostly. Cookiebot, CookieYes and similar tools handle the defaults and updates through their GTM templates. You still need to confirm the defaults run on Consent Initialisation and that all four signals are being sent. Verify rather than assume.

The short version

Set deny-by-default before any Google tag loads. Update the signals when the visitor chooses, and remember that choice. Wire it into your platform in the right position, then verify with Tag Assistant that the before state reads denied. That is Consent Mode v2, and it takes an afternoon rather than a project.

Consent Mode v2GTMGA4PrivacyShopify

Want this handled for you?

We are a founder-led studio in Toronto. If you would rather not do this yourself, we set it up properly, at a fixed price, and hand you everything.

Book a discovery call