Skip to content
← Back to Blog

Built-In consent vs Additional consent in GTM

GTM has two consent mechanisms and most people don't realize they're separate. Here's how Built-In and Additional consent work, when you need each one, and what happens when they conflict.

GTM has two consent mechanisms that work independently. Built-In consent checks are enforced by the tag template itself. Additional consent checks are configured by whoever manages the container. They serve different purposes, apply to different tags, and the container JSON doesn't clearly distinguish between them. Most consent confusion in GTM traces back to treating them as one thing when they're two.

Built-In consent checks

When you create a Google Ads Conversion tag in GTM, the tag template includes consent logic that you can't edit. It's visible in the GTM UI as greyed-out fields under "Consent Settings." The tag automatically checks specific consent types before deciding how to behave.

For native Google tags, Built-In consent controls what happens when consent is denied. Rather than simply not firing, the tag fires in a degraded mode. GA4 sends cookieless pings (gcs=G100) containing page URL, referrer, and timestamp, but no cookies and no user identifiers. Google Ads sends modeled conversion signals. Google uses these pings for conversion modeling, recovering an estimated 65-80% of the conversion data that would otherwise be lost. This is how Advanced Consent Mode works: tags always fire, but what they send depends on consent state.

The Built-In consent types vary by template:

Tag templateBuilt-In consent types
Google Ads Conversion (awct)ad_storage, ad_personalization, ad_user_data
Google Ads Remarketing (sp)ad_storage, ad_personalization, ad_user_data
Google Conversion Linker (gclidw)ad_storage, ad_personalization, ad_user_data
GA4 Event (gaawe)analytics_storage
GA4 Configuration (googtag)analytics_storage
Custom HTMLNone
LinkedIn InsightNone
Reddit PixelNone
Community templatesVaries (check the template)

The last four rows are the important ones. Custom HTML tags, third-party platform tags, and most community templates have no Built-In consent. They don't have template-level logic that checks consent state. If consent is denied, they either fire fully or don't fire at all, depending on whether someone configured Additional consent checks.

Additional consent checks

Additional consent is a user-configured gate you can add to any tag. In the GTM UI, it appears under a tag's consent settings with three options:

Not set. The default state. The tag hasn't been reviewed for consent. GTM shows an orange warning badge when you try to publish with tags in this state. In the container JSON, there's no consentSettings property on the tag.

No additional consent required. The tag relies on Built-In consent checks, or it's exempt from consent requirements. In the container JSON, this maps to consentStatus: NOT_NEEDED. For native Google tags with correct Built-In consent, this is the recommended setting.

Require additional consent for tag to fire. A hard block. The tag won't fire at all unless the visitor has granted all specified consent types. Unlike Built-In consent, there's no degraded mode. The tag either fires fully or stays completely silent. In the JSON, this shows as consentStatus: NEEDED with a consentType specifying which types are required.

When you need Additional consent

For tags without Built-In protection. A Custom HTML tag that loads a LinkedIn pixel has no template-enforced consent logic. If you want it gated behind ad_storage, you configure that as an Additional consent check. Same for any tag where the template doesn't include its own consent awareness: Reddit tracking, Salesloft, HubSpot Custom HTML implementations, and any script you're loading through Custom HTML.

For these tags, Additional consent is the only consent mechanism available. Without it, the tag fires unconditionally regardless of the visitor's consent choice.

When you don't

For Google native tags where Built-In consent is already correct. A Google Ads Conversion tag with Built-In checks for ad_storage, ad_personalization, and ad_user_data already has the consent coverage it needs. Setting Additional consent to "No additional consent required" (NOT_NEEDED) is Google's recommended setup. The Built-In checks handle the consent behavior, including the cookieless ping mode when consent is denied.

What your CMP classification has to do with this

Built-In consent checks don't operate in isolation. They respond to consent signals, and those signals come from your consent management platform. The CMP (Cookiebot, OneTrust, CookieYes) communicates the visitor's consent state to GTM through consent mode commands, and that state is determined by how the CMP classifies cookies.

If your CMP classifies _ga as "Necessary," the consent signal for analytics_storage is always "granted." Built-In checks on GA4 tags pass even when the visitor hasn't explicitly consented to analytics. The CMP told the browser that GA4 cookies are essential, so consent mode was never invoked.

Built-In consent doesn't fail on its own. It responds to what the CMP tells it. If the CMP's cookie classification is wrong, the consent signal is wrong, and Built-In checks act on bad data. This is why auditing GTM tag consent settings and auditing your CMP dashboard are separate tasks. Both need to be right for either to work as intended.

The double-gate problem

The most common consent misconfiguration in production containers is someone adding Additional consent on top of correct Built-In consent. Here's what that looks like.

A Google Ads Conversion tag has Built-In consent for ad_storage, ad_personalization, and ad_user_data. Someone adds an Additional consent check requiring analytics_storage. The tag now needs both ad consent AND analytics consent to fire. A visitor grants ad consent but not analytics consent. Built-In checks pass. The Additional check fails. The tag stays silent. The conversion is lost.

This happens when someone copies consent settings from a GA4 tag to an ad tag, or adds analytics_storage to everything because it seems safer. The intent is protective but the result is suppressed conversion data. It's harder to diagnose than a straightforward misconfiguration because both consent mechanisms are doing exactly what they're configured to do. They're just conflicting with each other.

The fix is removing the unnecessary Additional check. In the container JSON, that means changing consentStatus: NEEDED with consentType: analytics_storage to consentStatus: NOT_NEEDED. If you don't know about Built-In consent, that looks like you're removing consent protection entirely. You're not. You're removing a redundant gate that conflicts with the template-enforced consent the tag already has.

Quick reference

Tag typeHas Built-In consent?Additional consent needed?
Google Ads (native template)Yes: ad_storage, ad_personalization, ad_user_dataNo. NOT_NEEDED is correct.
GA4 (native template)Yes: analytics_storageNo. NOT_NEEDED is correct.
Custom HTMLNoYes. Configure the appropriate consent types.
LinkedIn InsightNoYes. ad_storage at minimum.
Reddit PixelNoYes. ad_storage at minimum.
Community templatesVariesCheck the template. If no Built-In, add Additional.

The distinction matters most when you're reading a container export or the output from an automated scan. NOT_NEEDED on a native Google Ads tag is the correct configuration. NOT_NEEDED on a Custom HTML tag that loads an advertising pixel is a consent gap. Same JSON value, completely different meaning.

TagManifest distinguishes between these cases using a Built-In consent map that knows what each tag template enforces. It flags the double-gate pattern specifically, and it evaluates NOT_NEEDED differently depending on whether the tag has Built-In protection or not.

Audit your GTM container

TagManifest gives you an instant health score and prioritized fixes.

Scan Your Container