If your consent default fires after GTM loads other tags — Google Analytics or Google Ads requests showing up in DevTools before Consent Mode's default has been set, even though you know you configured one — the cause is almost never a missing default. It's an ordering problem: the tag that sets the default is racing against the tags it's supposed to gate, and sometimes losing. This article is the deeper, GTM-specific version of failure mode #1 from why Google Consent Mode v2 isn't working — worth reading this one specifically if you've confirmed that the default is racing, and want the full trigger-level fix rather than the short version.
The fix: Consent Initialization - All Pages
GTM ships a trigger type built specifically to solve this: Consent Initialization - All Pages, available in the trigger type picker alongside Page View, DOM Ready, and the rest — not something you need to create or configure conditions for. Unlike every other trigger type, tags assigned to it are guaranteed to fire before any other tag in the container, on every page load, without exception. That guarantee is the entire fix.
How to check what you're currently using: in your GTM workspace, open the tag that
sets your consent default (either a custom HTML tag calling gtag('consent', 'default', {...}), or GTM's built-in Consent Settings tag type). Check its trigger. If it's anything
other than Consent Initialization - All Pages — Page View, DOM Ready, Window Loaded, a
custom event, anything else — that's the bug, and it explains why the behavior can look
intermittent: unordered triggers sometimes let the default win the race, sometimes not,
which is exactly why a single manual check can miss it.
The fix: change the tag's trigger to Consent Initialization - All Pages. See Google's own documentation on setting up consent mode for the full reference this trigger type is part of.
Why tag priority and sequencing don't fix this the same way
It's a common next step to try raising the consent tag's priority number, or using Tag Sequencing (Setup/Cleanup tags) to force it earlier. Neither actually solves the root problem: priority only orders tags within the same trigger, and Tag Sequencing controls one tag firing relative to another specific tag, not the consent default relative to every tag in the container generally. Both can reduce how often the race is lost without eliminating it — which produces the worst version of this bug: rare enough to pass casual testing, common enough to still leak pre-consent data in production.
Confirming the fix actually worked
How to check: after switching the trigger, clear your cookies (or use a fresh
incognito window) and run the same DevTools check covered in how to check if cookies fire
before consent — the consent entry with
"default" should be the first or among the very first dataLayer entries. Reload several
times to confirm it's consistent, not just correct on one lucky run, since consistency
across repeated loads is exactly what this fix is supposed to guarantee.
If your container has multiple consent-setting tags
Occasionally a container ends up with more than one tag trying to set the consent default
— left over from a CMP migration, or a custom implementation added alongside a CMP's
native one. If you have two tags both calling gtag('consent', 'default', ...), whichever
fires last silently overwrites whichever fired first, and unordered triggers make this
just as inconsistent as the single-tag version of this bug. Search your container for every
tag referencing consent or gtag before assuming there's only one to fix.
If you'd rather not check this by hand every time
A pre-consent scan checks exactly this: whether the consent default is present before any
other tracking tag fires, across a real first-time page load — the same race condition
this article is about, checked automatically instead of manually reloading and inspecting
dataLayer yourself.
— Petrus, ConsentCheck founder. This is the single most common GTM container issue I see when auditing a "should be working" Consent Mode setup — it's a trigger dropdown, not a rewrite.