Getting Started with Google Consent Mode v2
Implement Google Consent Mode v2 on WordPress without breaking your analytics. The architecture, the tags that matter, and the pitfalls that cause silent data loss.
Google Consent Mode v2 is the bridge between two things that fight: privacy regulations that demand explicit user consent before tracking, and analytics platforms that expect tag fires to happen. Without Consent Mode, the "decline" button on your cookie banner kills your analytics; with it, you keep modeled conversions and aggregate signals while respecting consent. This is what it actually takes to implement on WordPress without breaking either side.
Why v2 specifically
Consent Mode shipped in 2020 as a way for Google tags to adjust behaviour based on user consent state. v2, which became required for EEA, UK, and Swiss traffic in March 2024, added two new consent signals — ad_user_data and ad_personalization— required for any site running Google Ads or remarketing. If you operate in Europe and your consent banner doesn't pass v2 signals, your remarketing and audience features quietly degrade.
In 2026 the same pressure is present in more jurisdictions — California's CCPA/CPRA framework, Brazil's LGPD, Quebec's Law 25, and a growing list of US state laws (Colorado, Virginia, Connecticut, Utah). Treating Consent Mode v2 as "EU only" is a mistake; the architecture is right for any site that takes consent seriously.
The architecture in three pieces
Consent Mode is not a plugin. It's a contract between three components that need to agree:
- A consent-management platform (CMP). The cookie banner and the persistence layer that remembers what the user chose. Common choices: Cookiebot, OneTrust, Iubenda, CookieYes, Klaro, and our own Cookie Consent plugin. The CMP needs to be Google-certified for v2 if you want the full TCF integration.
- A tag manager that respects the consent signals. Google Tag Manager is the canonical option, but you can wire consent into hand-rolled gtag.js as well. The key idea: every tag knows what consent it requires, and only fires if those slots are granted.
- The default consent state, set BEFORE any tag fires. This is the part most implementations get wrong. The browser needs to see
gtag('consent', 'default', ...)before the Google tag library loads — otherwise the tag has already fired and consent is moot.
The consent signals you need to know
Six consent slots, each can be granted or denied:
ad_storage— cookies for adsad_user_data— sending user data for ad purposes (NEW in v2)ad_personalization— personalized advertising (NEW in v2)analytics_storage— cookies for analyticsfunctionality_storage— cookies for the site to functionpersonalization_storage— cookies for site personalizationsecurity_storage— security-related cookies (CSRF tokens, etc.) — usually granted by default
A common newcomer mistake: granting all signals after consent but leaving the EEA-specific ad_user_data and ad_personalization at denied. The site looks compliant but Google Ads remarketing degrades silently. Test the signals being passed, not just whether the banner works.
The default-state script — the part most people get wrong
The default consent block must run before any Google tag. On WordPress, the cleanest place is the very top of <head>, output via wp_head at priority 1:
add_action( 'wp_head', 'mxt_consent_mode_default', 1 );
function mxt_consent_mode_default() {
?>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){ dataLayer.push(arguments); }
// Default = denied for all advertising/analytics signals.
// Granted only for security, which most CMPs treat as essential.
gtag('consent', 'default', {
ad_storage: 'denied',
ad_user_data: 'denied',
ad_personalization: 'denied',
analytics_storage: 'denied',
functionality_storage: 'denied',
personalization_storage: 'denied',
security_storage: 'granted',
wait_for_update: 500
});
// Mark that the page is region-gated for the EEA + UK + CH.
// (Adjust regions to match your actual user base.)
gtag('set', 'ads_data_redaction', true);
gtag('set', 'url_passthrough', true);
</script>
<?php
}The wait_for_update: 500 tells Google to hold tag fires for 500ms after page load while the CMP makes its decision. If the user has a stored consent choice, the CMP issues an immediate gtag('consent', 'update', ...) — and tags fire with the right signals. If the user is undecided, tags fire in "modeled" mode, which sends cookieless pings that Google uses for aggregate modeling.
The update from your CMP
When the user makes a choice, the CMP issues an update. Most certified CMPs do this automatically; for a hand-rolled banner, the call looks like:
function userAcceptedAll() {
gtag('consent', 'update', {
ad_storage: 'granted',
ad_user_data: 'granted',
ad_personalization: 'granted',
analytics_storage: 'granted',
functionality_storage: 'granted',
personalization_storage: 'granted'
});
}
function userRejectedAll() {
gtag('consent', 'update', {
ad_storage: 'denied',
ad_user_data: 'denied',
ad_personalization: 'denied',
analytics_storage: 'denied',
functionality_storage: 'denied',
personalization_storage: 'denied'
});
}What "modeled" conversions actually mean
When users decline, you don't get cookies — but Google still gets cookieless pings (timestamp, page, referrer). These pings feed Google's modeling system, which estimates conversions and sessions you'd have measured if everyone consented. The modeled numbers show up in GA4 and Google Ads tagged with a modeling indicator.
Modeled data is not a substitute for direct measurement — it's a partial recovery. Sites with ~30% consent rates typically recover 50–70% of conversion attribution through modeling. Without Consent Mode v2, you recover zero. That's the tradeoff this whole system exists to address.
Wiring it into WordPress
A few practical wiring choices:
- If you use GTM, install GTM via a plugin like GTM4WP or hand-rolled
wp_headoutput. Inside GTM, mark every Google tag with the appropriate "Additional consent checks" in v2 mode — the GTM UI surfaces these since 2024. - If you use Site Kit(Google's official WP plugin), v2 support is built in but you still need to wire your CMP to call the update.
- If you hand-roll, use
wp_headat priority 1 for the default block and ensure your CMP's JS loads after that block but before any other Google tag.
For sites with WooCommerce, the order matters even more — see our checkout optimization guide for how consent and conversion tracking interact at the checkout step.
Testing — the part you cannot skip
Use Google's Tag Assistant browser extension to inspect what consent signals are being sent. Open it on your site, fire your consent banner, click each option, and confirm the signals match what the user chose. The most common silent failure is the banner saying "accepted" while the page still shows all signals as denied — usually because the default block ran after the page-view tag.
Use the GA4 DebugView with a debug-mode override to confirm events arrive with the right consent state. Use the GTM Preview mode to walk the tag-firing sequence and verify each tag respects its consent gate.
Common pitfalls
- Default block runs too late.Symptom: tags fire as "granted" even when the user hasn't chosen yet. Fix: move the default block to
wp_headpriority 1 (or even hard-coded intoheader.phpabove all enqueued scripts). - CMP doesn't issue v2 update calls. Symptom:
ad_user_datastays denied even when user accepted. Fix: upgrade to a v2-certified CMP version, or patch your hand-rolled banner. - Two consent banners on the page. Common when a plugin and theme both ship one. Pick one, kill the other. They will fight over consent state.
- Caching ate the script. If you see consent mode failing on the first page-load only, your page cache is serving a pre-injection version. Bypass cache for visitors without consent cookies.
- EU detection is wrong.Don't roll your own GeoIP for consent gating. Use a CMP that handles it, and assume the worst case (consent required) on cache misses.
Consent Mode v2 done right keeps your data flowing while respecting user choice. Done wrong, you have neither — broken analytics AND a banner that doesn't actually gate anything. For sites where this matters and getting it wrong has compliance implications, our WordPress development service includes the full Consent Mode wiring as part of any launch. Or — if you want to handle the consent layer yourself — our Cookie Consent plugin ships with v2-aware defaults out of the box.
Need help putting this into practice?
MaxtDesign builds the AI-powered web stacks the articles describe — from agentic workflows to performance-first WordPress + WooCommerce. Talk to us about your project.