Consent for Non-Google Tags
Google’s Consent Mode only controls Google’s tags. Meta Pixel, TikTok Pixel, LinkedIn Insight Tag, Pinterest Tag, Criteo, and hundreds of other ad networks have no native awareness of Consent Mode signals. They fire whenever their trigger conditions are met, regardless of what the user consented to.
This means your consent implementation is only half-complete if you have addressed only Google’s tags. Every non-Google advertising tag in your container needs its own consent gate.
The three approaches
Section titled “The three approaches”There are three practical ways to gate non-Google tags on consent. Each has different trade-offs in terms of complexity, reliability, and maintenance burden.
Approach 1: Trigger conditions with consent variable (recommended)
Section titled “Approach 1: Trigger conditions with consent variable (recommended)”Add the consent state as a condition on the trigger that fires your non-Google tags. The tag will not fire unless consent is granted.
Step 1: Create a Custom JavaScript Variable that reads the current consent state:
// Variable name: "JS - Ad Consent Granted"function() { try { var consentData = window.google_tag_data && window.google_tag_data.ics && window.google_tag_data.ics.entries;
if (!consentData) return false;
var adStorage = consentData.ad_storage; var adUserData = consentData.ad_user_data; var adPersonalization = consentData.ad_personalization;
// All three advertising types must be granted for ad tags return (adStorage && adStorage.update === 'granted') && (adUserData && adUserData.update === 'granted') && (adPersonalization && adPersonalization.update === 'granted'); } catch(e) { return false; }}Step 2: On each advertising tag’s trigger (All Pages, Page View, or custom event), add a trigger condition:
- Variable:
{{JS - Ad Consent Granted}} - Operator: equals
- Value:
true
The tag will only fire on events where advertising consent is confirmed as granted.
Analytics-only variant (for analytics tags that are not advertising-related):
// Variable name: "JS - Analytics Consent Granted"function() { try { var consentData = window.google_tag_data && window.google_tag_data.ics && window.google_tag_data.ics.entries;
if (!consentData) return false;
var analyticsStorage = consentData.analytics_storage; return analyticsStorage && analyticsStorage.update === 'granted'; } catch(e) { return false; }}Approach 2: Tag sequencing with a consent-check setup tag
Section titled “Approach 2: Tag sequencing with a consent-check setup tag”Create a setup tag that explicitly checks consent and fails if consent is not granted. Any tag that uses this setup tag will not fire if the setup tag fails.
Consent gate setup tag (Custom HTML):
<script>(function() { var requiredConsent = 'advertising'; // 'analytics' or 'advertising'
function getConsentState(type) { try { var data = window.google_tag_data && window.google_tag_data.ics && window.google_tag_data.ics.entries; if (!data) return 'unknown';
if (type === 'advertising') { var adStorage = data.ad_storage && data.ad_storage.update; var adUserData = data.ad_user_data && data.ad_user_data.update; return (adStorage === 'granted' && adUserData === 'granted') ? 'granted' : 'denied'; }
if (type === 'analytics') { return data.analytics_storage && data.analytics_storage.update === 'granted' ? 'granted' : 'denied'; }
return 'unknown'; } catch(e) { return 'unknown'; } }
if (getConsentState(requiredConsent) !== 'granted') { // Cause the setup tag to "fail" — GTM will block dependent tags throw new Error('Consent not granted for: ' + requiredConsent); }})();</script>Configure dependent tags: On each advertising tag, go to Advanced Settings → Tag Sequencing → Setup Tag. Select your consent gate tag and check Don’t fire [tag name] if [setup tag] fails.
This approach is useful when you want to centrally manage the consent check rather than adding conditions to every individual trigger.
Approach 3: Dataayer-based consent trigger
Section titled “Approach 3: Dataayer-based consent trigger”Use the consent event in your dataLayer to fire tags only when consent is explicitly granted. This approach requires the dataLayer consent pattern from Consent State via DataLayer.
Create two triggers per tag:
Trigger A — Consent granted on this page load (new consent or returning visitor):
- Trigger Type: Custom Event
- Event Name:
consent_update - Trigger Conditions:
{{DLV - consent.advertising}}equalstrue - Fire on: All custom events matching name
Trigger B — Page view when consent was already granted (returning visitor, consent restored):
- Trigger Type: Page View
- Trigger Conditions:
{{DLV - consent.advertising}}equalstrue
Apply both triggers to your advertising tags. Trigger A fires the tag when the user accepts consent. Trigger B fires it on page load for returning visitors who already accepted.
Consent state variable: alternative approach using dataLayer
Section titled “Consent state variable: alternative approach using dataLayer”If you are pushing consent state to the dataLayer (as described in Consent State via DataLayer), you can use a simpler Data Layer Variable instead of the Custom JavaScript approach:
- Create a Data Layer Variable:
DLV - Consent Advertising, readsconsent.advertising - Add as a trigger condition:
DLV - Consent Advertisingequalstrue
This is simpler to configure but slightly less reliable if the dataLayer push hasn’t fired yet when the trigger evaluates.
Building a reusable consent gate
Section titled “Building a reusable consent gate”For containers with many non-Google tags, building a reusable consent gate reduces configuration overhead:
Create a custom “Consent Gate” variable that returns the appropriate value based on the tag context:
// Variable name: "JS - Consent Gate"// Input: variable reads consent.type from a constant or data layerfunction() { var consentType = {{Constant - Required Consent Type}}; // Set "Constant - Required Consent Type" to "advertising" or "analytics" // on each tag using Constant variables per tag
try { var consentData = window.google_tag_data && window.google_tag_data.ics && window.google_tag_data.ics.entries; if (!consentData) return false;
switch (consentType) { case 'advertising': return consentData.ad_storage && consentData.ad_storage.update === 'granted' && consentData.ad_user_data && consentData.ad_user_data.update === 'granted'; case 'analytics': return consentData.analytics_storage && consentData.analytics_storage.update === 'granted'; case 'functional': return consentData.functionality_storage && consentData.functionality_storage.update === 'granted'; default: return false; } } catch(e) { return false; }}Tag-specific notes
Section titled “Tag-specific notes”Meta Pixel
Section titled “Meta Pixel”Meta Pixel has a native consent API: fbq('consent', 'grant') and fbq('consent', 'revoke'). Use this in combination with trigger-based gating:
// In your consent update callbackif (advertisingConsentGranted) { fbq('consent', 'grant');} else { fbq('consent', 'revoke');}Meta’s Community Template from the Gallery respects this pattern when properly configured.
TikTok Pixel
Section titled “TikTok Pixel”TikTok Pixel does not have a native consent API as of this writing. Use trigger-based gating (Approach 1 or 2) to block the pixel entirely when advertising consent is denied.
<!-- TikTok base code — gate entire tag on consent --><script> // Check consent first — don't even initialize TikTok without consent if ({{JS - Ad Consent Granted}}) { !function (w, d, t) { // TikTok pixel initialization code }(window, document, 'script'); ttq.load('YOUR_PIXEL_ID'); ttq.page(); }</script>LinkedIn Insight Tag
Section titled “LinkedIn Insight Tag”LinkedIn’s Insight Tag does not natively support Consent Mode. Gate it on advertising consent with Approach 1:
- Add
{{JS - Ad Consent Granted}} equals trueas a trigger condition to your LinkedIn Insight Tag trigger - Also gate the tag initialization — LinkedIn’s tag creates a global
_linkedin_data_partner_idsobject which persists in memory even if the tag doesn’t fire on this page load
Third-party Community Templates
Section titled “Third-party Community Templates”Many third-party vendor templates from the Community Gallery have built-in consent support. Check the template’s documentation for whether it reads Consent Mode signals natively. If it does, configure the required consent types in the template settings. If it doesn’t, use one of the three approaches above.
Verifying non-Google tag gating
Section titled “Verifying non-Google tag gating”After implementing consent gates, verify:
- Open a fresh incognito browser (no existing consent)
- Do not interact with the consent banner
- Open DevTools → Network
- Check that no requests to Meta’s pixel endpoint (
connect.facebook.net), TikTok (analytics.tiktok.com), or LinkedIn (px.ads.linkedin.com) appear - Now accept advertising consent
- Verify that pixel initialization requests appear after consent is granted
Also test the denial case:
- Fresh incognito session
- Reject advertising consent (but accept analytics)
- Verify analytics tags fire but advertising tags do not
- Check Network tab: no requests to advertising pixel domains
Common mistakes
Section titled “Common mistakes”Gating only the page view trigger, not the conversion trigger. If Meta Pixel fires on page load and on purchase events, both triggers need the consent condition — not just the page view.
Using equals 'true' (string) instead of equals true (boolean). Data Layer Variable types matter. If consent is pushed as a boolean true but your condition checks for the string 'true', the condition never matches.
Not gating the tag script injection. Some advertising tags load a third-party script via injectScript even when the trigger doesn’t fire — the script loads but no event is sent. Ensure the entire initialization code is inside the consent check, not just the event firing code.
Testing with an existing session. If the browser has advertising consent from a previous session, all tags will appear to fire correctly even if your gates are broken for new visitors.