Cookie Consent Implementation Guide: Legally Compliant Consent Management

Implement cookie consent that complies with GDPR, ePrivacy, CCPA, and global regulations. Covers consent banners, cookie categorization, and CMP integration.

E
ECOSIRE Research and Development Team
|March 16, 20268 min read1.6k Words|

Part of our Compliance & Regulation series

Read the complete guide

Cookie Consent Implementation Guide: Legally Compliant Consent Management

Over EUR 400 million in GDPR fines have been issued specifically for cookie consent violations since 2020. The French CNIL fined Google EUR 150 million and Facebook EUR 60 million for making it easier to accept cookies than to refuse them. Cookie consent is no longer a checkbox exercise --- it is a heavily enforced area of privacy law with specific technical requirements.

This guide covers the legal requirements, technical implementation, and ongoing management of cookie consent for websites and web applications.

Key Takeaways

  • Under GDPR and ePrivacy, consent must be obtained BEFORE setting non-essential cookies --- not after
  • Consent must be as easy to withdraw as it is to give (one-click refuse, not buried in settings)
  • Cookie walls ("accept or leave") are illegal in most EU member states
  • Google Consent Mode v2 is required for Google Analytics and Ads in the EEA since March 2024

RequirementEU (GDPR + ePrivacy)UK (PECR + UK GDPR)US (CCPA/state laws)Brazil (LGPD)Canada (PIPEDA)
Prior consent for non-essential cookiesYes (opt-in)Yes (opt-in)No (opt-out model)Yes (opt-in)Implied consent allowed
Consent banner requiredYesYesNot required (but recommended)YesRecommended
Granular choices (by category)YesYesNot requiredYesRecommended
Equal prominence for accept/refuseYesYesN/AYesN/A
Cookie wall allowedNo (in most states)NoN/ANoN/A
Consent record requiredYesYesNoYesYes
Consent renewal periodMax 12 monthsMax 12 monthsN/ANot specifiedNot specified
Cookie policy requiredYes (detailed)Yes (detailed)Yes (if tracking)YesYes

The ePrivacy Directive covers not just HTTP cookies but all technologies that store or access information on the user's device:

  • HTTP cookies (first-party and third-party)
  • LocalStorage and SessionStorage
  • IndexedDB
  • Device fingerprinting
  • Tracking pixels / web beacons
  • ETags used for tracking

Standard Categories

CategoryConsent Required?ExamplesDefault State
Strictly necessaryNoSession cookies, CSRF tokens, load balancer cookies, authenticationAlways on
Functional / preferencesYesLanguage preference, theme preference, saved cartOff (until consent)
Analytics / performanceYesGoogle Analytics, Hotjar, Plausible (with cookies)Off (until consent)
Marketing / advertisingYesGoogle Ads, Facebook Pixel, retargeting cookiesOff (until consent)

Auditing Your Cookies

Before implementing consent, audit every cookie your website sets:

// Browser console: list all cookies
document.cookie.split(';').forEach(c => console.log(c.trim()));

// Or use a scanning tool
// cookiebot.com/en/cookie-checker
// 2gdpr.com

Document each cookie:

Cookie NameCategoryPurposeDurationFirst/Third Party
ecosire_authStrictly necessaryAuthenticationSessionFirst-party
ecosire_refreshStrictly necessaryToken refresh7 daysFirst-party
NEXT_LOCALEStrictly necessaryLanguage preference1 yearFirst-party
_gaAnalyticsGoogle Analytics visitor ID2 yearsThird-party (Google)
_fbpMarketingFacebook Pixel tracking90 daysThird-party (Facebook)

Technical Implementation

CMPFree TierGDPR CompliantGoogle CMP PartnerIAB TCF 2.2
CookiebotUp to 1 pageYesYesYes
OneTrustNoYesYesYes
OsanoUp to 5K visitorsYesYesNo
TermlyBasic planYesYesNo
Cookie-ScriptUp to 1 siteYesYesNo

Option 2: Custom Implementation

For teams that want full control:

// lib/cookie-consent.ts
type ConsentCategory = 'necessary' | 'functional' | 'analytics' | 'marketing';

interface ConsentPreferences {
  necessary: true; // Always true, cannot be changed
  functional: boolean;
  analytics: boolean;
  marketing: boolean;
  timestamp: string;
  version: string;
}

const CONSENT_COOKIE = 'ecosire_consent';
const CONSENT_VERSION = '2.0';
const CONSENT_DURATION = 365; // days

export function getConsent(): ConsentPreferences | null {
  const cookie = document.cookie
    .split(';')
    .find(c => c.trim().startsWith(`${CONSENT_COOKIE}=`));

  if (!cookie) return null;

  try {
    const prefs = JSON.parse(decodeURIComponent(cookie.split('=')[1]));
    // Invalidate if consent version changed
    if (prefs.version !== CONSENT_VERSION) return null;
    return prefs;
  } catch {
    return null;
  }
}

export function setConsent(preferences: Omit<ConsentPreferences, 'necessary' | 'timestamp' | 'version'>) {
  const consent: ConsentPreferences = {
    necessary: true,
    ...preferences,
    timestamp: new Date().toISOString(),
    version: CONSENT_VERSION,
  };

  const expires = new Date(Date.now() + CONSENT_DURATION * 86400000).toUTCString();
  document.cookie = `${CONSENT_COOKIE}=${encodeURIComponent(JSON.stringify(consent))}; expires=${expires}; path=/; SameSite=Lax`;

  // Apply consent decisions
  applyConsent(consent);

  return consent;
}

function applyConsent(consent: ConsentPreferences) {
  if (consent.analytics) {
    // Initialize Google Analytics
    loadScript('https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX');
  }

  if (consent.marketing) {
    // Initialize marketing pixels
    loadScript('https://connect.facebook.net/en_US/fbevents.js');
  }

  if (!consent.analytics) {
    // Remove analytics cookies
    deleteCookie('_ga');
    deleteCookie('_gid');
  }

  if (!consent.marketing) {
    // Remove marketing cookies
    deleteCookie('_fbp');
    deleteCookie('_fbc');
  }
}

Required for Google Analytics and Google Ads in the EEA since March 2024:

<!-- Set default consent state BEFORE loading Google tags -->
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}

  // Default: deny all until user consents
  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', // Always granted (necessary)
    'wait_for_update': 500 // Wait for CMP
  });
</script>

<!-- Load Google Tag Manager -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>

When the user provides consent:

// Update consent state when user interacts with banner
function updateGoogleConsent(preferences) {
  gtag('consent', 'update', {
    'ad_storage': preferences.marketing ? 'granted' : 'denied',
    'ad_user_data': preferences.marketing ? 'granted' : 'denied',
    'ad_personalization': preferences.marketing ? 'granted' : 'denied',
    'analytics_storage': preferences.analytics ? 'granted' : 'denied',
    'functionality_storage': preferences.functional ? 'granted' : 'denied',
    'personalization_storage': preferences.functional ? 'granted' : 'denied',
  });
}

  • Banner appears BEFORE any non-essential cookies are set
  • "Accept all" and "Refuse all" buttons have equal visual prominence
  • Granular category selection available (not just all-or-nothing)
  • No pre-checked boxes for non-essential categories
  • Clear, plain language explanation of each category
  • Link to full cookie policy
  • Consent withdrawal accessible at any time (e.g., footer link)
  • No cookie wall (must be able to use the site without consenting)
  • Consent recorded with timestamp and version

Accessibility Requirements

  • Banner is keyboard navigable
  • Screen reader compatible (ARIA labels)
  • Sufficient color contrast
  • Does not block essential content permanently

For websites wanting to avoid cookie consent banners entirely:

ToolCookiesGDPR Consent NeededData LocationPrice
PlausibleNoneNoEU$9/month
FathomNoneNoEU/US/Canada$14/month
UmamiNoneNoSelf-hostedFree
Simple AnalyticsNoneNoEU$9/month
Matomo (cookie-free config)OptionalNo (without cookies)Self-hostedFree

Using cookie-free analytics eliminates the need for analytics consent, simplifying your consent banner to only cover marketing cookies (if used).


Frequently Asked Questions

Do we need a cookie banner if we only use necessary cookies?

No. If you only use strictly necessary cookies (authentication, CSRF, load balancing), no consent is required and no banner is needed. However, you should still disclose these cookies in your privacy policy. The moment you add analytics (Google Analytics) or any third-party tracking, a consent banner becomes legally required in the EU.

Is it legal to use a "soft opt-in" (continue browsing = consent)?

No, not under GDPR. The European Data Protection Board has explicitly stated that continued browsing, scrolling, or similar passive actions do not constitute valid consent. Consent must be a clear, affirmative action --- clicking a button that says "Accept" or similar. Soft opt-in was ruled non-compliant in Planet49 (CJEU, 2019).

How do we handle consent for single-page applications?

For SPAs, check consent state on initial page load and on every route change. If consent has not been given, do not initialize tracking scripts. Store consent preferences in a first-party cookie (which itself is strictly necessary for remembering consent). When the user provides consent, initialize tracking scripts without requiring a page reload.

Do we need cookie consent for our Odoo website?

If your Odoo website serves EU visitors and uses analytics, marketing pixels, or functional cookies beyond what is strictly necessary, yes. Odoo has a basic cookie notice but it does not meet GDPR standards. Implement a proper CMP like Cookiebot or build a custom solution. ECOSIRE provides Odoo website services that include GDPR-compliant cookie consent.


What Comes Next

Cookie consent is the most visible aspect of web privacy compliance. Combine it with privacy by design for your application architecture, data governance for your full data program, and cybersecurity regulations for broader compliance.

Contact ECOSIRE for cookie consent implementation and privacy compliance consulting.


Published by ECOSIRE -- helping businesses implement privacy compliance that users trust.

E

Written by

ECOSIRE Research and Development Team

Building enterprise-grade digital products at ECOSIRE. Sharing insights on Odoo integrations, e-commerce automation, and AI-powered business solutions.

Chat on WhatsApp