Consent Mode helps you respect visitor choices while still running analytics where allowed. This tutorial covers a practical default-denied, update-on-accept pattern with GTM and GA4.
What you will build
- Consent default state before tags fire
- A simple accept / reject control that calls `gtag('consent', 'update', …)`
- GTM Consent Overview alignment for ad_storage and analytics_storage
Prerequisites
- GTM + GA4 already installed
- Legal review for your markets (this is a technical starter, not legal advice)
- A cookie banner UI (custom or CMP)
Step-by-step
- Set consent defaults to denied for `analytics_storage` and `ad_storage` before GTM loads (or use GTM Consent Initialization tags).
- On Accept, call consent update with granted values and push a `consent_update` dataLayer event.
- On Reject, keep denied and optionally store the choice in `localStorage`.
- In GTM, enable Consent Overview and require analytics consent on the GA4 Configuration tag.
- Test both paths in Preview: no GA4 hits when denied; hits when granted.
Default consent (before GTM)
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('consent', 'default', {
ad_storage: 'denied',
analytics_storage: 'denied',
wait_for_update: 500
});
</script>Update on accept
export function grantAnalyticsConsent() {
window.dataLayer = window.dataLayer || [];
function gtag(...args: unknown[]) {
window.dataLayer.push(args);
}
gtag("consent", "update", {
analytics_storage: "granted",
ad_storage: "denied", // grant only if Ads tags need it
});
window.dataLayer.push({ event: "consent_update", analytics: "granted" });
}Verify
- Denied path: GA4 DebugView stays quiet
- Granted path: `page_view` appears
- Returning visitor: stored choice applied before tags
Notes
- Europe often needs a stricter CMP; North America still benefits from clear opt-in UX
- Never bury reject behind dark patterns
- Document what loads without consent (strictly necessary only)
Next steps
Wire your real banner component, then map consent regions if you serve the USA, Canada, Europe, Australia, and Asia with different defaults.


