Problem

  • Cookie banner doesn't show on page load.
  • Users don't see the consent request.

Diagnostic Steps

Step 1: Check if TermsFeed Cookie Consent is loaded

// Open browser console and type:
console.log(typeof cookieconsent);

// Should output: "object"
// If "undefined", script didn't load

Step 2: Check for JavaScript errors

  1. Open DevTools (F12)
  2. Go to Console tab
  3. Look for errors

Common errors include:

  1. cookieconsent is not defined
  2. Uncaught ReferenceError
  3. Failed to load resource

Step 3: Verify the TermsFeed Cookie Consent script placement

<!-- ❌ WRONG - Script in <head> without async -->
<head>
    <script src="//www.termsfeed.com/public/cookie-consent/4.2.0/cookie-consent.js"></script>
    <script>
        cookieconsent.run({ / config / });
    </script>
</head>

<!-- ✅ CORRECT - Script before </body> with DOMContentLoaded -->
<body>
    <!-- content -->

    <script src="//www.termsfeed.com/public/cookie-consent/4.2.0/cookie-consent.js"></script>
    <script>
        document.addEventListener('DOMContentLoaded', function () {
            cookieconsent.run({ / config / });
        });
    </script>
</body>

Common causes and fixes

Cause 1: The user already consented

// Check if user has cookie
console.log(document.cookie);
// Look for: cookie_consent_level=...

// To test banner, clear cookie:
document.cookie = 'cookie_consent_level=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
// Then reload page

Cause 2: An ad blocker is blocking TermsFeed Cookie Consent

The solution is to integrate a proxy server to serve TermsFeed Cookie Consent.

Cause 3: Content Security Policy blocks loading

The error in Developer Tools > Console might be Refused to load the script ... violates the following Content Security Policy directive

The solution is to update CSP headers:

Content-Security-Policy: script-src 'self' www.termsfeed.com 'unsafe-inline'

Cause 4: Wrong configuration

Common mistakes on configuration:


// 1. Missing quotes
cookieconsent.run({
    consent_type: express  // ❌ Missing quotes
});

// 2. Trailing comma (IE issue)
cookieconsent.run({
    "consent_type": "express",  // ❌ Trailing comma
});

// 3. Missing DOMContentLoaded
cookieconsent.run({ / config / });  // ❌ Runs before DOM ready

// ✅ CORRECT:
document.addEventListener('DOMContentLoaded', function () {
    cookieconsent.run({
        "consent_type": "express",
        "website_name": "My Site",
        "language": "en"
    });
});

Cause 5: Conflicting scripts

Another script may prevent TermsFeed Cookie Consent banner from showing up.

The soluton is to check the scripts load order.

// Test isolation
// Temporarily remove ALL other scripts
// Keep ONLY cookie consent
// If banner shows, you have a conflict

// Common conflicts:
// - Other cookie consent tools
// - Privacy plugins
// - Ad blockers (client-side)

Debug Mode

Enable debug logging:

cookieconsent.run({
    "consent_type": "express",
    "website_name": "My Site",
    "debug": true  // Enable debug logging
});

// Check console for debug messages:
// [CookieConsent] Banner initialized
// [CookieConsent] User has no consent
// [CookieConsent] Showing banner

Scripts are not being blocked

Problem

"I tagged my Google Analytics script with data-cookie-consent='tracking' but it still fires before user accepts cookies!"

Diagnostic steps

Step 1: Verify script tagging

<!-- ❌ WRONG -->
<script type="text/javascript" data-cookie-consent="tracking">
  // GA code
</script>

<!-- ✅ CORRECT -->
<script type="text/plain" data-cookie-consent="tracking">
  // GA code
</script>

<!-- Key difference: type="text/plain" NOT type="text/javascript" -->

Step 2: Check the Network tab

  1. Open DevTools → Network tab
  2. Clear cookies
  3. Reload page (before accepting)
  4. Filter for your tracking scripts
  5. Tagged scripts should NOT appear in Network tab

Step 3: Check if cookies are being set

  1. DevTools → Application → Cookies
  2. Before accepting: No Google Analytics cookies
  3. After accepting: _ga, _gid cookies appear

Common Causes and Fixes

Cause 1: Script loaded before Cookie Consent

<!-- ❌ WRONG ORDER -->
<script type="text/plain" data-cookie-consent="tracking">
  // GA code
</script>
<script src="//www.termsfeed.com/public/cookie-consent/4.2.0/cookie-consent.js"></script>

<!-- ✅ CORRECT ORDER -->
<script src="//www.termsfeed.com/public/cookie-consent/4.2.0/cookie-consent.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
    cookieconsent.run({ / config / });
});
</script>

<!-- NOW tag scripts below -->
<script type="text/plain" data-cookie-consent="tracking">
  // GA code
</script>

Cause 2: External script is not blocked

<!-- ❌ External scripts need different approach -->
<script src="https://www.googletagmanager.com/gtag/js?id=G-XXX" data-cookie-consent="tracking"></script>

<!-- ✅ CORRECT - wrap in type="text/plain" -->
<script type="text/plain" data-cookie-consent="tracking">
  var script = document.createElement('script');
  script.src = 'https://www.googletagmanager.com/gtag/js?id=G-XXX';
  script.async = true;
  document.head.appendChild(script);

  script.onload = function() {
    // Initialize GA
    window.dataLayer = window.dataLayer || [];
    function gtag(){dataLayer.push(arguments);}
    gtag('js', new Date());
    gtag('config', 'G-XXX');
  };
</script>

Cause 3: Using Google Tag Manager

The common problem is when GTM loads before consent.

The solution is to not tag GTM container itself. Instead:

  1. Load GTM normally (without tagging)
  2. Configure tags INSIDE GTM to fire only with consent
  3. Use built-in Consent Mode or custom triggers
<!-- Don't tag the GTM container -->
<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-XXXX');</script>

<!-- Instead, push consent state to dataLayer -->
<script>
document.addEventListener('DOMContentLoaded', function () {
    cookieconsent.run({
        // ... config ...
        "callbacks": {
            "scripts_specific_loaded": (level) => {
                // Push to dataLayer
                window.dataLayer = window.dataLayer || [];
                window.dataLayer.push({
                    'event': 'cookie_consent_update',
                    'consent_level': level
                });
            }
        }
    });
});
</script>

<!-- Then in GTM, create trigger:
   Event: cookie_consent_update
   Condition: consent_level equals tracking
-->

Cause 4: Cookies are set by server

If a backend server sets cookies before JavaScript runs, the solution is to code more server-side logic.

<?php
// Check if user has consented (server-side)
$hasConsent = false;
if (isset($_COOKIE['cookie_consent_level'])) {
    $consentLevel = json_decode(urldecode($_COOKIE['cookie_consent_level']), true);
    $hasConsent = in_array('tracking', $consentLevel);
}

// Only set analytics cookies if user consented
if ($hasConsent) {
    setcookie('analytics_id', $user_id, time() + 86400, '/');
}
?>

Problem

"User accepts cookies, but when they navigate to another page or refresh, the banner appears again!"

Diagnostic Steps

Step 1: Check if a cookie is being set

// After accepting, open console and run:
console.log(document.cookie);

// Should see something like:
// cookie_consent_level=%5B%22strictly-necessary%22%2C%22tracking%22%5D

Step 2: Check the cookie properties

// DevTools → Application → Cookies
// Look for: cookie_consent_level

// Check:
// ✓ Domain: Should match your domain
// ✓ Path: Should be /
// ✓ Expires: Should be future date (1 year)
// ✓ HttpOnly: Should be unchecked (JavaScript needs access)
// ✓ Secure: Depends on your settings
// ✓ SameSite: Strict or Lax

Common Causes and Fixes

Cause 1: Cookie path mismatch

Problem

Cookie set for /subdir but page is at /

Solution

Ensure cookie uses root path.

// Cookie should be set for path=/
// This happens automatically, but verify in DevTools

// If using cookie_domain parameter, DON'T include path:
cookieconsent.run({
    "cookie_domain": ".example.com",  // ✅ No path needed
    // Other config...
});

Cause 2: Browser blocking cookies

Problem

Browser privacy settings prevent cookie storage.

Solution

The user must adjust browser settings.

// Detect if cookies are blocked
function areCookiesEnabled() {
    try {
        document.cookie = 'test=test; SameSite=Strict';
        const enabled = document.cookie.indexOf('test=') !== -1;
        document.cookie = 'test=; expires=Thu, 01 Jan 1970 00:00:00 UTC';
        return enabled;
    } catch (e) {
        return false;
    }
}

// Show warning if cookies disabled
if (!areCookiesEnabled()) {
    alert('Cookies are disabled in your browser. Please enable them to save your preferences.');
}

Cause 3: Conflicting cookie deletion

Problem

Another script or browser extension deletes cookies.

Solution

Check what's deleting cookies

// Check what's deleting cookies
// Add console log on page load:
console.log('Cookies on load:', document.cookie);

// If consent cookie is missing, something deleted it
// Common culprits:
// - Privacy extensions (Privacy Badger, uBlock)
// - Browser auto-delete (Firefox Enhanced Tracking Protection)
// - Another script calling document.cookie clear

Cause 4: Subdomain issues

Problem

Cookie set on www.example.com doesn't work on example.com

Solution

Use cookie_domain parameter.

cookieconsent.run({
    "cookie_domain": ".example.com",  // Note the leading dot!
    // This makes cookie valid for ALL subdomains
    // Other config...
});

Cause 5: HTTPS/HTTP mismatch

Problem

Cookie set with Secure flag on HTTPS, but site switches to HTTP.

Solution

Ensure consistent protocol OR remove the secure flag for testing.

cookieconsent.run({
    "cookie_secure": false,  // Set to true ONLY if site is always HTTPS
    // Other config...
});

// For production HTTPS sites:
cookieconsent.run({
    "cookie_secure": true,  // ✅ Recommended for HTTPS
    // Other config...
});

Problem

"I implemented Google Consent Mode V2 but Google Analytics still shows 0 events even when users accept cookies."

Diagnostic Steps

Step 1: Verify gtag function exists

// Open console:
console.log(typeof gtag);
// Should output: "function"

// If "undefined", gtag didn't load

Step 2: Check dataLayer

// Check dataLayer contents:
console.log(window.dataLayer);

// Should see consent events:
// [{event: "consent", ...}, {event: "config", ...}]

Step 3: Use Google Tag Assistant

  1. Install: Tag Assistant Chrome Extension
  2. Enable debugging
  3. Reload page
  4. Check for consent mode events

Common Causes and Fixes

Cause 1: Wrong implementation order

<!-- ❌ WRONG ORDER -->
<script src="//www.termsfeed.com/public/cookie-consent/4.2.0/cookie-consent.js"></script>
<script>
gtag('consent', 'default', {'analytics_storage': 'denied'});
</script>

<!-- ✅ CORRECT ORDER -->
<!-- 1. Set default consent FIRST -->
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('consent', 'default', {
    'ad_storage': 'denied',
    'analytics_storage': 'denied'
});
</script>

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

<!-- 3. THEN Cookie Consent -->
<script src="//www.termsfeed.com/public/cookie-consent/4.2.0/cookie-consent.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
    cookieconsent.run({
        // ... config with callbacks ...
    });
});
</script>

Cause 2: Missing callbacks_force parameter

// ❌ Without callbacks_force, callbacks won't fire for Consent Mode
cookieconsent.run({
    "callbacks": {
        "scripts_specific_loaded": (level) => {
            gtag('consent', 'update', {'analytics_storage': 'granted'});
        }
    }
    // Missing: "callbacks_force": true
});

// ✅ CORRECT
cookieconsent.run({
    "callbacks": {
        "scripts_specific_loaded": (level) => {
            gtag('consent', 'update', {'analytics_storage': 'granted'});
        }
    },
    "callbacks_force": true  // Required for Consent Mode!
});

Cause 3: Typo in consent types

// ❌ Common typos:
gtag('consent', 'update', {
    'analytic_storage': 'granted'  // ❌ Missing 's'
});

gtag('consent', 'update', {
    'ad_store': 'granted'  // ❌ Should be 'ad_storage'
});

// ✅ CORRECT spellings:
gtag('consent', 'update', {
    'analytics_storage': 'granted',  // ✅
    'ad_storage': 'granted',         // ✅
    'ad_user_data': 'granted',       // ✅
    'ad_personalization': 'granted'  // ✅
});

Cause 4: Wrong category mapping

// Make sure you're mapping correct categories
"callbacks": {
    "scripts_specific_loaded": (level) => {
        switch (level) {
            case 'tracking':  // ✅ Analytics
                gtag('consent', 'update', {
                    'analytics_storage': 'granted'
                });
                break;
            case 'targeting':  // ✅ Advertising
                gtag('consent', 'update', {
                    'ad_storage': 'granted',
                    'ad_user_data': 'granted',
                    'ad_personalization': 'granted'
                });
                break;
        }
    }
}
// After accepting cookies, check consent state:
console.log(google_tag_manager['GTM-XXXX'].dataLayer.get('consent'));

// Should show:
// {
//   ad_storage: "granted",
//   analytics_storage: "granted",
//   ...
// }

Cross-Domain Issues

Problem

"I set cookie_domain to '.example.com' but the banner still shows on every subdomain. Users are annoyed!"

Diagnostic Steps

Step 1: Verify cookie domain

// DevTools → Application → Cookies
// Look for: cookie_consent_level
// Domain column should show: .example.com (with leading dot)

// If it shows: www.example.com (no dot)
// Then cookie_domain parameter isn't working

Step 2: Check cookie from the subdomain

// On www.example.com:
console.log(document.cookie);
// Should include: cookie_consent_level=...

// Then navigate to shop.example.com:
console.log(document.cookie);
// Should STILL include the same cookie

Step 3: Test in incognito

  1. Open incognito window
  2. Visit www.example.com
  3. Accept cookies
  4. Note cookie value
  5. Visit shop.example.com
  6. Check if same cookie exists

Common Causes and Fixes

Cause 1: Missing leading dot

// ❌ WRONG
"cookie_domain": "example.com"  // No leading dot

// ✅ CORRECT
"cookie_domain": ".example.com"  // With leading dot

Cause 2: Different configurations

Problem

Main domain and subdomain have different configs.

// www.example.com has:
cookieconsent.run({
    "website_name": "Main Site",
    "cookie_domain": ".example.com"
});

// shop.example.com has:
cookieconsent.run({
    "website_name": "Shop",  // ❌ Different config
    "cookie_domain": ".example.com"
});

Solution

Use IDENTICAL configuration on all domains.

// ✅ SOLUTION: Use IDENTICAL configuration on all domains
const SHARED_CONFIG = {
    "notice_banner_type": "headline",
    "consent_type": "express",
    "website_name": "Example",  // Same everywhere
    "cookie_domain": ".example.com",
    // ... rest of config
  };

// Use on ALL domains
cookieconsent.run(SHARED_CONFIG);
  

Cause 3: Browser blocking third-party cookies

Problem

Safari, Firefox, Brave block cross-site cookies by default.

Solution

This affects DIFFERENT domains, not subdomains.

  • Subdomains (.example.com) = First-party cookies ✅ Should work
  • Different TLDs (example.com vs example.co.uk) = Third-party ❌ Won't work
// For actual cross-domain (different TLDs), use backend sync:
"callbacks": {
    "user_consent_saved": () => {
        // Sync to backend
        fetch('https://api.example.com/sync-consent', {
            method: 'POST',
            body: JSON.stringify({
                consent: getConsentState(),
                user_id: getUserId()
            })
        });
    }
}

Cause 4: Cookie not visible due to path

// Cookie might be set for specific path
// Check: DevTools → Application → Cookies → Path column

  // Should be: /
// If not, cookie won't work across site

// Force root path (this should be default):
// Note: TermsFeed Cookie Consent should handle this automatically
// But if you're manually setting cookies:
document.cookie = 'cookie_consent_level=...; path=/; domain=.example.com';

Character Encoding Issues

Problem

"Special characters in my banner text show as �� or weird symbols"

Solution

Ensure UTF-8 encoding.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">  <!-- ✅ Must have this -->
    <title>My Site</title>
</head>
<body>
    <script src="//www.termsfeed.com/public/cookie-consent/4.2.0/cookie-consent.js" charset="UTF-8"></script>
    <!-- ✅ charset="UTF-8" in script tag -->
</body>
</html>

For custom text:

cookieconsent.run({
    "website_name": "Café Français",  // ✅ UTF-8 characters work
    "language": "fr"  // Use appropriate language
});