Tracking Without Consent | Blue Frog Docs

Tracking Without Consent

Fixing tracking pixels and scripts that fire before user consent is obtained, violating GDPR and CCPA.

Tracking Without Consent

What This Means

Tracking without consent occurs when analytics, advertising, or marketing scripts load and collect user data before obtaining proper user consent. This is one of the most common and serious privacy violations.

What happens when tracking fires pre-consent:

  • Cookies set before user permission
  • Page views tracked without authorization
  • User behavior data collected illegally
  • Advertising pixels fire prematurely
  • Personal data sent to third parties without consent
  • IP addresses and device fingerprints collected

Impact:

  • GDPR fines: Up to €20 million or 4% of annual revenue
  • CCPA fines: Up to $7,500 per intentional violation
  • Legal liability and litigation risk
  • Loss of user trust
  • Invalid/unreliable analytics data
  • Ad platform account suspension

Common scenarios:

  • Google Analytics firing on page load
  • Meta Pixel tracking before consent banner interaction
  • Hotjar/FullStory recording sessions immediately
  • Google Tag Manager tags firing pre-consent
  • TikTok Pixel loading before approval
  • Embedded social media widgets tracking users
  • Chat widgets collecting data on load

How to Diagnose

1. Network Tab Test (Primary Method)

This is the most reliable way to detect pre-consent tracking:

  1. Open incognito/private browser window (fresh state)
  2. Open Developer Tools (F12 or right-click > Inspect)
  3. Go to Network tab
  4. Clear any existing requests (trash icon)
  5. Visit your website
  6. DO NOT interact with consent banner
  7. Look for these domains in Network tab:

Analytics platforms:

  • google-analytics.com/g/collect (GA4)
  • google-analytics.com/collect (Universal Analytics)
  • stats.g.doubleclick.net
  • analytics.google.com

Advertising pixels:

  • connect.facebook.net/en_US/fbevents.js (Meta Pixel)
  • facebook.com/tr/ (Meta tracking)
  • googleadservices.com/pagead/conversion
  • analytics.tiktok.com
  • ct.pinterest.com
  • snap.licdn.com/li.lms-analytics

Session replay/heatmaps:

  • static.hotjar.com
  • fullstory.com/s/fs.js
  • mouseflow.com
  • crazyegg.com

If ANY of these load before consent interaction, you have a violation.

  1. Open DevTools > Application tab > Cookies
  2. Clear all cookies
  3. Reload page WITHOUT interacting with consent banner
  4. Check which cookies are set

Only essential cookies should appear:

  • Session cookies (required for functionality)
  • Security cookies (CSRF tokens)
  • Shopping cart cookies
  • Load balancer cookies

These cookies indicate violations if set pre-consent:

  • _ga, _gid, _gat (Google Analytics)
  • _fbp, _fbc (Meta Pixel)
  • IDE, DSID (Google Ads)
  • _hjSessionUser, _hjSession (Hotjar)
  • _ttp (TikTok)
  • li_sugr (LinkedIn)

3. Browser Extension Test

Use these extensions to detect tracking:

Ghostery:

  1. Install Ghostery extension
  2. Visit your site (don't interact with consent)
  3. Click Ghostery icon
  4. Count trackers detected before consent

Facebook Pixel Helper:

  1. Install Facebook Pixel Helper
  2. Visit your site
  3. Check if pixel fires before consent granted

Tag Assistant (Google):

  1. Install Tag Assistant Legacy
  2. Enable recording
  3. Visit site without consent interaction
  4. Stop recording
  5. Check which tags fired

4. GTM Preview Mode Test

If using Google Tag Manager:

  1. Open GTM container
  2. Click Preview
  3. Enter your website URL
  4. In preview panel, check "Tags Fired" BEFORE you interact with consent banner
  5. Only "Consent Initialization" or essential tags should fire

Tags that should NOT fire pre-consent:

  • Google Analytics tags
  • Advertising tags (Meta, Google Ads)
  • Remarketing tags
  • Third-party marketing tags
  • Analytics event tags

5. Console Warning Check

Some platforms show warnings:

// Open Console tab (F12)
// Look for warnings like:
"Unconsented cookie usage detected"
"Analytics loaded without consent mode"

General Fixes

Step 1: Add consent initialization BEFORE GTM

Add this code in your <head> section BEFORE your GTM script:

<!-- Consent Mode Initialization -->
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}

  // Set default consent to denied
  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', // Usually always granted
    'wait_for_update': 500 // Wait for CMP to update
  });

  // Optional: Set region-specific defaults
  gtag('consent', 'default', {
    'ad_storage': 'denied',
    'analytics_storage': 'denied',
    'region': ['AT', 'BE', 'BG', 'HR', 'CY', 'CZ', 'DK', 'EE', 'FI', 'FR', 'DE',
               'GR', 'HU', 'IE', 'IT', 'LV', 'LT', 'LU', 'MT', 'NL', 'PL', 'PT',
               'RO', 'SK', 'SI', 'ES', 'SE', 'GB', 'IS', 'LI', 'NO'] // EEA countries
  });
</script>

<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXX');</script>

Step 2: Update consent when user grants permission

Your consent banner should trigger this when user accepts:

// When user accepts all
gtag('consent', 'update', {
  'ad_storage': 'granted',
  'ad_user_data': 'granted',
  'ad_personalization': 'granted',
  'analytics_storage': 'granted',
  'functionality_storage': 'granted',
  'personalization_storage': 'granted'
});

// When user accepts only analytics
gtag('consent', 'update', {
  'analytics_storage': 'granted',
  'functionality_storage': 'granted'
});

Step 3: Configure tags in GTM to require consent

For each tag in GTM:

  1. Open tag settings
  2. Go to Advanced Settings > Consent Settings
  3. Add required consent:
    • Analytics tags: Require analytics_storage
    • Advertising tags: Require ad_storage, ad_user_data, ad_personalization
    • Functionality tags: Require functionality_storage

Recommended CMPs with GTM integration:

Cookiebot:

  • Auto-blocks scripts until consent
  • Native GTM consent mode integration
  • Automatic cookie categorization
  • Multi-language support

OneTrust:

  • Enterprise-grade compliance
  • Pre-built templates
  • Consent mode v2 support
  • Detailed consent logging

Osano:

  • Developer-friendly API
  • Automatic script detection
  • Consent mode integration
  • Affordable pricing

Quantcast Choice:

  • IAB TCF 2.2 compliant
  • Free tier available
  • Consent mode support
  • CMP for publishers

Implementation example (Cookiebot):

<!-- Cookiebot by Usercentrics CMP -->
<script id="Cookiebot" src="https://consent.cookiebot.com/uc.js"
        data-cbid="YOUR-COOKIEBOT-ID"
        data-blockingmode="auto"
        data-gtm-consent-mode="true"
        type="text/javascript"></script>

<!-- Cookiebot handles consent mode automatically -->

3. Block Scripts with Type Attribute

For hardcoded scripts, use type="text/plain" to prevent execution:

Before (non-compliant):

<script src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXX"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', 'G-XXXXXXX');
</script>

After (compliant):

<script type="text/plain" data-cookiecategory="analytics"
        src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXX"></script>
<script type="text/plain" data-cookiecategory="analytics">
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', 'G-XXXXXXX');
</script>

CMP changes type from text/plain to text/javascript after consent.

4. Defer Third-Party Script Loading

Lazy load scripts after consent:

// Consent granted event listener
window.addEventListener('CookiebotOnAccept', function() {
  // User accepted consent, load scripts

  if (Cookiebot.consent.statistics) {
    // Load analytics
    loadGoogleAnalytics();
  }

  if (Cookiebot.consent.marketing) {
    // Load advertising pixels
    loadMetaPixel();
    loadGoogleAds();
  }
});

function loadGoogleAnalytics() {
  var script = document.createElement('script');
  script.async = true;
  script.src = 'https://www.googletagmanager.com/gtag/js?id=G-XXXXXXX';
  document.head.appendChild(script);

  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', 'G-XXXXXXX');
}

function loadMetaPixel() {
  !function(f,b,e,v,n,t,s)
  {if(f.fbq)return;n=f.fbq=function(){n.callMethod?
  n.callMethod.apply(n,arguments):n.queue.push(arguments)};
  if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
  n.queue=[];t=b.createElement(e);t.async=!0;
  t.src=v;s=b.getElementsByTagName(e)[0];
  s.parentNode.insertBefore(t,s)}(window, document,'script',
  'https://connect.facebook.net/en_US/fbevents.js');
  fbq('init', 'YOUR-PIXEL-ID');
  fbq('track', 'PageView');
}

5. Platform-Specific Implementations

Shopify:

  • Use Customer Privacy API
  • Enable consent mode in theme settings
  • Install Shopify-approved consent apps

WordPress:

  • Install GDPR-compliant consent plugin
  • Configure GTM plugin to wait for consent
  • Use Complianz or CookieYes plugins

Wix:

  • Enable cookie consent in Wix settings
  • Configure consent categories
  • Wix automatically blocks trackers

Testing Your Implementation

Complete Testing Checklist

  1. Clear all cookies and site data
  2. Open incognito/private window
  3. Open DevTools (Network + Application tabs)
  4. Load your site
  5. Before interacting with consent banner:
    • Check Network tab - no tracking requests
    • Check Cookies - only essential cookies
    • Check Console - no tracking errors
  6. Click "Reject All" or "Decline":
    • Tracking should remain blocked
    • Navigate site - still no tracking
  7. Clear cookies again
  8. Reload and click "Accept All":
    • Tracking scripts now load
    • Cookies are set
    • Analytics fires
  9. Navigate to another page:
    • Tracking continues working
    • Consent preference persisted
  10. Clear cookies and reload:
    • Consent banner appears again
    • Tracking blocked until consent

Automated Testing Tools

Cookie consent validators:

Common Mistakes to Avoid

  1. Loading GTM before consent initialization

    • Always add consent mode code BEFORE GTM
  2. Not configuring tag consent requirements

    • Every non-essential tag needs consent settings
  3. Using "Consent Initialization - All Pages" trigger wrong

    • This fires on page load, before consent
    • Use for consent mode setup only, not tracking
  4. Forgetting to test in incognito

    • Testing in normal browser may have cached consent
  5. Assuming consent mode works without configuration

    • Must configure both consent code AND tag settings
  6. Not handling consent state changes

    • Users can revoke consent - track state changes

Platform-Specific Guides

Platform Guide
Shopify Shopify Consent API
WordPress WordPress Consent Plugins
Wix Wix Cookie Consent
Squarespace Squarespace GDPR Settings
Webflow Webflow Cookie Banner
Magento Magento Cookie Compliance
BigCommerce BigCommerce Cookie Consent

Regulatory Requirements

GDPR (Article 6, 7)

  • Consent required before non-essential cookies
  • Opt-in, not opt-out - must be affirmative action
  • Granular consent - different categories
  • Easy to withdraw - revocation as easy as granting
  • No pre-ticked boxes - default must be declined

CCPA

  • Opt-out mechanism - "Do Not Sell My Info"
  • Notice before collection - inform users
  • Under 16 requires opt-in - stricter for minors
  • Strictly necessary exception - only essential cookies exempt
  • Consent before storage - obtain consent first
  • Clear information - explain cookie purposes

Further Reading

// SYS.FOOTER