Back to Blog
Technical

E-commerce Privacy: Extensions for Magento and PrestaShop

David Kim, WordPress DeveloperNovember 11, 202510 min read
MagentoPrestaShopE-commercePlugins

TLDR: Cookie consent on Magento 2 and PrestaShop requires platform-specific integration—generic plugins often break checkout.

Read full summary Technical guide to implementing consent management on Magento 2 and PrestaShop. Covers platform architecture differences, plugin selection criteria, checkout integration, and avoiding common pitfalls that hurt conversions. *Summary by Claude AI*
--- title: "Magento 2 and PrestaShop Cookie Consent: Complete Plugin Implementation Guide 2025" slug: "magento-prestashop-cookie-consent-plugins" excerpt: "Master cookie consent implementation on Magento 2 and PrestaShop with our comprehensive guide covering top plugins, custom development, checkout protection, and multi-store configurations for GDPR and ePrivacy compliance." category: "E-commerce Platforms" tags: ["Magento 2", "PrestaShop", "Cookie Consent", "E-commerce", "GDPR", "Plugin Development"] publishedAt: "2025-01-18" readTime: "22 min read" --- # Magento 2 and PrestaShop Cookie Consent: Complete Plugin Implementation Guide Implementing cookie consent on enterprise e-commerce platforms like Magento 2 and PrestaShop presents unique challenges that simple WordPress plugins cannot address. These platforms have complex JavaScript architectures, RequireJS module loaders, multi-store configurations, and checkout flows that must remain functional even when marketing cookies are blocked. This comprehensive guide walks you through every aspect of implementing robust cookie consent on both platforms. ## Understanding the E-commerce Cookie Consent Challenge Unlike content websites where blocking cookies simply disables analytics, e-commerce platforms rely on cookies for critical functionality. Shopping carts, wishlists, recently viewed products, and checkout sessions all use cookies. A poorly implemented consent solution can destroy conversions, while an overly permissive one creates legal liability. ### The Cookie Landscape on E-commerce Platforms Before implementing any solution, you need to understand what cookies your platform sets: **Essential Cookies (Always Allowed):** - Session identifiers (PHPSESSID, form_key) - Shopping cart data (cart_id, quote_id) - Authentication tokens - CSRF protection tokens - Currency and store preferences **Analytics Cookies (Require Consent):** - Google Analytics (_ga, _gid, _gat) - Hotjar (_hj*) - Facebook Pixel (_fbp) - Platform analytics **Marketing Cookies (Require Consent):** - Retargeting pixels - Ad network identifiers - Cross-site tracking cookies - Social media trackers **Functional Cookies (Gray Area):** - Recently viewed products - Wishlist functionality - Product comparisons - Persistent login The functional category is where most e-commerce implementations struggle. These enhance user experience but aren't strictly necessary for purchasing. ## Magento 2 Cookie Consent Implementation Magento 2's architecture is complex, with RequireJS managing JavaScript loading, UI components handling frontend interactions, and a sophisticated event system. Your cookie consent solution must integrate deeply with all these systems. ### Understanding Magento 2's JavaScript Architecture Magento 2 uses RequireJS as its JavaScript module loader. Every script on the page loads through RequireJS, which presents both a challenge and an opportunity for cookie consent: ```javascript // How Magento 2 loads scripts through RequireJS require(['jquery', 'Magento_Customer/js/customer-data'], function($, customerData) { // This code runs after modules are loaded var cart = customerData.get('cart'); }); ``` To implement cookie consent properly, you need to intercept RequireJS loading and conditionally block modules based on consent state. ### Top Magento 2 Cookie Consent Extensions #### 1. Amasty Cookie Consent (Recommended) Amasty's Cookie Consent is the most comprehensive solution for Magento 2, offering deep integration with the platform's architecture. **Key Features:** - RequireJS integration for script blocking - Cookie groups with granular control - GeoIP-based banner display - Automatic cookie scanning - Google Consent Mode v2 support - IAB TCF 2.2 compatibility **Installation via Composer:** ```bash # Add Amasty repository (requires license) composer config repositories.amasty composer https://composer.amasty.com/enterprise/ # Install the module composer require amasty/module-gdpr-cookie-compliance # Enable and deploy php bin/magento module:enable Amasty_GdprCookie php bin/magento setup:upgrade php bin/magento setup:di:compile php bin/magento setup:static-content:deploy -f php bin/magento cache:flush ``` **Configuration for Cookie Groups:** ```xml Required for the store to function. Cannot be disabled. Help us understand how visitors interact with our store. Used to deliver personalized advertisements. ``` #### 2. MageWorx GDPR Cookie Compliance MageWorx offers a solid alternative with excellent multi-store support: **Installation:** ```bash composer require mageworx/module-gdpr-cookie php bin/magento setup:upgrade php bin/magento setup:di:compile php bin/magento setup:static-content:deploy -f ``` **Multi-store Configuration:** ```php storeManager = $storeManager; } public function getCookieConfigForCurrentStore(): array { $storeId = $this->storeManager->getStore()->getId(); $storeCode = $this->storeManager->getStore()->getCode(); // Define store-specific configurations $configs = [ 'eu_store' => [ 'show_banner' => true, 'default_consent' => false, 'tcf_enabled' => true, 'gcm_enabled' => true, ], 'us_store' => [ 'show_banner' => true, 'default_consent' => true, // Opt-out model for US 'tcf_enabled' => false, 'gcm_enabled' => true, ], 'uk_store' => [ 'show_banner' => true, 'default_consent' => false, 'tcf_enabled' => true, 'gcm_enabled' => true, ], ]; return $configs[$storeCode] ?? $configs['eu_store']; } } ``` ### Custom Magento 2 Cookie Consent Implementation For organizations requiring complete control, here's how to build a custom solution: **Module Structure:** ``` app/code/YourCompany/CookieConsent/ ├── registration.php ├── etc/ │ ├── module.xml │ ├── di.xml │ ├── frontend/ │ │ ├── routes.xml │ │ └── requirejs-config.js │ └── adminhtml/ │ └── system.xml ├── Block/ │ └── CookieBanner.php ├── Model/ │ ├── ConsentManager.php │ └── CookieRegistry.php ├── Controller/ │ └── Consent/ │ ├── Save.php │ └── Get.php ├── view/ │ └── frontend/ │ ├── layout/ │ │ └── default.xml │ ├── templates/ │ │ └── cookie-banner.phtml │ └── web/ │ ├── js/ │ │ ├── cookie-consent.js │ │ └── script-blocker.js │ └── css/ │ └── cookie-banner.css └── Plugin/ └── RequireJsBlocker.php ``` **Core Consent Manager:** ```php cookieManager = $cookieManager; $this->cookieMetadataFactory = $cookieMetadataFactory; $this->sessionManager = $sessionManager; $this->json = $json; } public function saveConsent(array $consents): void { $consentData = [ 'essential' => true, // Always true 'analytics' => $consents['analytics'] ?? false, 'marketing' => $consents['marketing'] ?? false, 'functional' => $consents['functional'] ?? false, 'timestamp' => time(), 'version' => $this->getConsentVersion(), ]; $metadata = $this->cookieMetadataFactory ->createPublicCookieMetadata() ->setDuration(self::CONSENT_COOKIE_DURATION) ->setPath($this->sessionManager->getCookiePath()) ->setDomain($this->sessionManager->getCookieDomain()) ->setSecure(true) ->setHttpOnly(false); // Must be accessible to JS $this->cookieManager->setPublicCookie( self::CONSENT_COOKIE_NAME, $this->json->serialize($consentData), $metadata ); // Remove cookies for denied categories $this->removeRejectedCookies($consents); } public function getConsent(): array { $consentCookie = $this->cookieManager->getCookie(self::CONSENT_COOKIE_NAME); if ($consentCookie) { try { $consent = $this->json->unserialize($consentCookie); // Check if consent version is current if (($consent['version'] ?? '') !== $this->getConsentVersion()) { return $this->getDefaultConsent(); } return $consent; } catch (\Exception $e) { return $this->getDefaultConsent(); } } return $this->getDefaultConsent(); } public function hasConsented(): bool { return $this->cookieManager->getCookie(self::CONSENT_COOKIE_NAME) !== null; } public function hasConsentFor(string $category): bool { $consent = $this->getConsent(); return $consent[$category] ?? false; } private function removeRejectedCookies(array $consents): void { $cookieRegistry = [ 'analytics' => ['_ga', '_gid', '_gat', '_gat_*'], 'marketing' => ['_fbp', '_fbc', 'fr', '_gcl_*'], 'functional' => ['recently_viewed_*', 'wishlist_*'], ]; foreach ($cookieRegistry as $category => $cookies) { if (!($consents[$category] ?? false)) { foreach ($cookies as $cookieName) { if (strpos($cookieName, '*') !== false) { // Pattern-based removal handled in JS continue; } $this->deleteCookie($cookieName); } } } } private function deleteCookie(string $name): void { $metadata = $this->cookieMetadataFactory ->createPublicCookieMetadata() ->setPath($this->sessionManager->getCookiePath()) ->setDomain($this->sessionManager->getCookieDomain()); $this->cookieManager->deleteCookie($name, $metadata); } private function getDefaultConsent(): array { return [ 'essential' => true, 'analytics' => false, 'marketing' => false, 'functional' => false, 'timestamp' => null, 'version' => $this->getConsentVersion(), ]; } private function getConsentVersion(): string { return '2025.01.18'; // Update when cookie policy changes } } ``` **RequireJS Script Blocker:** ```javascript // app/code/YourCompany/CookieConsent/view/frontend/web/js/script-blocker.js define([ 'jquery', 'mage/cookies' ], function($) { 'use strict'; return { blockedModules: { 'analytics': [ 'Magento_GoogleAnalytics/js/google-analytics', 'Magento_GoogleGtag/js/google-analytics', 'googleTagManagerScript' ], 'marketing': [ 'facebookPixel', 'googleAds', 'criteo' ] }, getConsent: function() { var consentCookie = $.mage.cookies.get('cookie_consent'); if (consentCookie) { try { return JSON.parse(consentCookie); } catch (e) { return null; } } return null; }, isModuleAllowed: function(moduleName) { var consent = this.getConsent(); if (!consent) { return false; // No consent = block non-essential } for (var category in this.blockedModules) { if (this.blockedModules[category].indexOf(moduleName) !== -1) { return consent[category] === true; } } return true; // Module not in any blocked category }, interceptRequireJS: function() { var self = this; var originalRequire = window.require; window.require = function(deps, callback, errback) { if (Array.isArray(deps)) { deps = deps.filter(function(dep) { var allowed = self.isModuleAllowed(dep); if (!allowed) { console.log('CookieConsent: Blocked module:', dep); } return allowed; }); } return originalRequire.call(this, deps, callback, errback); }; // Copy properties from original require for (var prop in originalRequire) { if (originalRequire.hasOwnProperty(prop)) { window.require[prop] = originalRequire[prop]; } } }, initialize: function() { this.interceptRequireJS(); } }; }); ``` **Cookie Banner Template:** ```php getConsentManager(); $showBanner = !$consentManager->hasConsented(); ?> ``` ### Protecting Checkout from Cookie Blocking The checkout process in Magento 2 must never be disrupted by cookie consent. Here's how to ensure checkout always works: ```php 'Session cookie with shop hash', 'PHPSESSID' => 'PHP Session ID', 'COOKIE_ACCEPTED' => 'Cookie consent state (if using built-in)', ]; // Common Third-Party Module Cookies $module_cookies = [ 'viewed_products' => 'Recently viewed products', 'compare_products' => 'Product comparison', 'wishlist_*' => 'Wishlist functionality', ]; ``` ### Top PrestaShop Cookie Consent Modules #### 1. PrestaShop Official GDPR Module The official module is free and provides a good baseline: **Installation:** 1. Download from PrestaShop Addons 2. Upload via Back Office → Modules → Upload Module 3. Configure in Modules → Module Manager → GDPR **Configuration Code:** ```php customer->id ?? null; if (!$customerId) { // Check cookie for guest consent return self::getGuestConsent($moduleName); } return Db::getInstance()->getValue( 'SELECT consent FROM `' . _DB_PREFIX_ . 'psgdpr_consent_log` WHERE id_customer = ' . (int)$customerId . ' AND module_name = "' . pSQL($moduleName) . '" ORDER BY date_add DESC' ); } } ``` #### 2. PrestaHero Cookie Law Pro (Recommended) PrestaHero's module offers the most comprehensive solution for PrestaShop: **Key Features:** - Automatic cookie scanning - Script blocking with RegEx patterns - YouTube/Vimeo embed blocking - Google Consent Mode integration - IAB TCF 2.2 support - Multi-language support **Custom Integration Example:** ```php name = 'your_module'; // ... standard constructor } public function hookDisplayHeader($params) { // Check if Cookie Law Pro is installed and consent is given if (Module::isEnabled('ph_cookielaw')) { $cookieConsent = $this->getCookieLawConsent(); if (!$cookieConsent['analytics']) { return ''; // Don't load analytics scripts } } return $this->display(__FILE__, 'views/templates/hook/header.tpl'); } private function getCookieLawConsent() { $cookie = Context::getContext()->cookie; $consent = json_decode($cookie->ph_cookielaw_consent ?? '{}', true); return [ 'essential' => true, 'analytics' => $consent['analytics'] ?? false, 'marketing' => $consent['marketing'] ?? false, 'functional' => $consent['functional'] ?? false, ]; } } ``` ### Custom PrestaShop Cookie Consent Module For complete control, here's how to build a custom module: **Module Structure:** ``` modules/customcookieconsent/ ├── customcookieconsent.php ├── config.xml ├── controllers/ │ └── front/ │ └── consent.php ├── classes/ │ ├── ConsentManager.php │ └── CookieScanner.php ├── views/ │ ├── templates/ │ │ └── hook/ │ │ ├── cookie_banner.tpl │ │ └── cookie_settings.tpl │ ├── js/ │ │ └── cookie-consent.js │ └── css/ │ └── cookie-banner.css └── translations/ ``` **Main Module File:** ```php name = 'customcookieconsent'; $this->tab = 'front_office_features'; $this->version = '1.0.0'; $this->author = 'Your Company'; $this->need_instance = 0; $this->bootstrap = true; parent::__construct(); $this->displayName = $this->l('Custom Cookie Consent'); $this->description = $this->l('GDPR-compliant cookie consent management'); $this->confirmUninstall = $this->l('Are you sure you want to uninstall?'); $this->ps_versions_compliancy = ['min' => '1.7', 'max' => _PS_VERSION_]; } public function install() { return parent::install() && $this->registerHook('displayHeader') && $this->registerHook('displayFooterBefore') && $this->registerHook('actionFrontControllerSetMedia') && $this->installDb(); } private function installDb() { $sql = 'CREATE TABLE IF NOT EXISTS `' . _DB_PREFIX_ . 'cookie_consent_log` ( `id_consent` INT UNSIGNED NOT NULL AUTO_INCREMENT, `id_customer` INT UNSIGNED NULL, `id_guest` INT UNSIGNED NULL, `consent_data` TEXT NOT NULL, `ip_address` VARCHAR(45) NOT NULL, `user_agent` VARCHAR(255) NULL, `date_add` DATETIME NOT NULL, `date_upd` DATETIME NOT NULL, PRIMARY KEY (`id_consent`), INDEX `idx_customer` (`id_customer`), INDEX `idx_guest` (`id_guest`), INDEX `idx_date` (`date_add`) ) ENGINE=' . _MYSQL_ENGINE_ . ' DEFAULT CHARSET=utf8mb4;'; return Db::getInstance()->execute($sql); } public function hookActionFrontControllerSetMedia() { $this->context->controller->registerStylesheet( 'cookie-consent-css', 'modules/' . $this->name . '/views/css/cookie-banner.css', ['media' => 'all', 'priority' => 100] ); $this->context->controller->registerJavascript( 'cookie-consent-js', 'modules/' . $this->name . '/views/js/cookie-consent.js', ['position' => 'head', 'priority' => 1] ); } public function hookDisplayFooterBefore($params) { $consentManager = new ConsentManager($this->context); if ($consentManager->hasConsented()) { return ''; // Don't show banner if already consented } $this->context->smarty->assign([ 'cookie_categories' => $this->getCookieCategories(), 'privacy_url' => $this->context->link->getCMSLink( Configuration::get('PS_CONDITIONS_CMS_ID') ), 'consent_save_url' => $this->context->link->getModuleLink( $this->name, 'consent', ['action' => 'save'] ), ]); return $this->display(__FILE__, 'views/templates/hook/cookie_banner.tpl'); } private function getCookieCategories() { return [ 'essential' => [ 'name' => $this->l('Essential'), 'description' => $this->l('Required for the store to function'), 'required' => true, 'cookies' => ['PrestaShop-*', 'PHPSESSID'], ], 'analytics' => [ 'name' => $this->l('Analytics'), 'description' => $this->l('Help us understand visitor behavior'), 'required' => false, 'cookies' => ['_ga', '_gid', '_gat'], ], 'marketing' => [ 'name' => $this->l('Marketing'), 'description' => $this->l('Used for targeted advertising'), 'required' => false, 'cookies' => ['_fbp', '_fbc', 'fr'], ], 'functional' => [ 'name' => $this->l('Functional'), 'description' => $this->l('Enhanced features like wishlists'), 'required' => false, 'cookies' => ['viewed_products', 'wishlist_*'], ], ]; } } ``` **Consent Manager Class:** ```php context = $context; } public function saveConsent(array $categories): bool { $consentData = [ 'essential' => true, 'analytics' => (bool)($categories['analytics'] ?? false), 'marketing' => (bool)($categories['marketing'] ?? false), 'functional' => (bool)($categories['functional'] ?? false), 'timestamp' => time(), 'version' => $this->getConsentVersion(), ]; // Save to cookie $this->context->cookie->__set( self::CONSENT_COOKIE_NAME, json_encode($consentData) ); // Log to database for audit $this->logConsent($consentData); // Delete cookies for rejected categories $this->cleanRejectedCookies($consentData); return true; } public function getConsent(): array { $cookieValue = $this->context->cookie->__get(self::CONSENT_COOKIE_NAME); if ($cookieValue) { $consent = json_decode($cookieValue, true); if (($consent['version'] ?? '') === $this->getConsentVersion()) { return $consent; } } return $this->getDefaultConsent(); } public function hasConsented(): bool { $consent = $this->getConsent(); return isset($consent['timestamp']); } public function hasConsentFor(string $category): bool { $consent = $this->getConsent(); return $consent[$category] ?? false; } private function logConsent(array $consentData): void { $customerId = $this->context->customer->id ?? null; $guestId = $this->context->cookie->id_guest ?? null; Db::getInstance()->insert('cookie_consent_log', [ 'id_customer' => $customerId, 'id_guest' => $guestId, 'consent_data' => pSQL(json_encode($consentData)), 'ip_address' => pSQL(Tools::getRemoteAddr()), 'user_agent' => pSQL($_SERVER['HTTP_USER_AGENT'] ?? ''), 'date_add' => date('Y-m-d H:i:s'), 'date_upd' => date('Y-m-d H:i:s'), ]); } private function cleanRejectedCookies(array $consent): void { $cookieMap = [ 'analytics' => ['_ga', '_gid', '_gat'], 'marketing' => ['_fbp', '_fbc', 'fr'], ]; foreach ($cookieMap as $category => $cookies) { if (!$consent[$category]) { foreach ($cookies as $cookieName) { if (isset($_COOKIE[$cookieName])) { setcookie($cookieName, '', time() - 3600, '/'); } } } } } private function getDefaultConsent(): array { return [ 'essential' => true, 'analytics' => false, 'marketing' => false, 'functional' => false, 'timestamp' => null, 'version' => $this->getConsentVersion(), ]; } private function getConsentVersion(): string { return Configuration::get('COOKIE_CONSENT_VERSION') ?: '1.0'; } } ``` **JavaScript for Script Blocking:** ```javascript // modules/customcookieconsent/views/js/cookie-consent.js (function() { 'use strict'; const CookieConsent = { config: { cookieName: 'cc_consent', blockedScripts: { analytics: [ 'google-analytics.com', 'googletagmanager.com', 'analytics.js', 'gtag.js' ], marketing: [ 'facebook.net', 'connect.facebook.net', 'fbevents.js', 'doubleclick.net' ] } }, init: function() { this.interceptScriptLoading(); this.blockInlineScripts(); this.setupBannerListeners(); }, getConsent: function() { const cookie = this.getCookie(this.config.cookieName); if (cookie) { try { return JSON.parse(cookie); } catch (e) { return null; } } return null; }, getCookie: function(name) { const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)')); return match ? decodeURIComponent(match[2]) : null; }, interceptScriptLoading: function() { const self = this; const originalCreateElement = document.createElement.bind(document); document.createElement = function(tagName) { const element = originalCreateElement(tagName); if (tagName.toLowerCase() === 'script') { const originalSetAttribute = element.setAttribute.bind(element); element.setAttribute = function(name, value) { if (name === 'src' && self.shouldBlockScript(value)) { console.log('CookieConsent: Blocked script:', value); return; } return originalSetAttribute(name, value); }; Object.defineProperty(element, 'src', { set: function(value) { if (self.shouldBlockScript(value)) { console.log('CookieConsent: Blocked script src:', value); return; } originalSetAttribute('src', value); }, get: function() { return element.getAttribute('src'); } }); } return element; }; }, shouldBlockScript: function(src) { const consent = this.getConsent(); if (!consent) { // No consent given, block all non-essential return this.isBlockedScript(src, 'analytics') || this.isBlockedScript(src, 'marketing'); } for (const category in this.config.blockedScripts) { if (!consent[category] && this.isBlockedScript(src, category)) { return true; } } return false; }, isBlockedScript: function(src, category) { const patterns = this.config.blockedScripts[category] || []; return patterns.some(pattern => src.includes(pattern)); }, blockInlineScripts: function() { // Find and neutralize inline scripts with data-category document.querySelectorAll('script[data-cookie-category]').forEach(script => { const category = script.getAttribute('data-cookie-category'); const consent = this.getConsent(); if (!consent || !consent[category]) { script.type = 'text/plain'; // Prevents execution } }); }, setupBannerListeners: function() { const banner = document.getElementById('cookie-consent-banner'); if (!banner) return; banner.addEventListener('click', (e) => { const action = e.target.dataset.action; switch (action) { case 'accept-all': this.saveConsent({ analytics: true, marketing: true, functional: true }); break; case 'reject-all': this.saveConsent({ analytics: false, marketing: false, functional: false }); break; case 'accept-selected': this.saveSelectedConsent(); break; } }); }, saveConsent: function(categories) { fetch(window.consentSaveUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(categories) }) .then(response => response.json()) .then(data => { if (data.success) { this.hideBanner(); if (categories.analytics || categories.marketing) { // Reload to enable blocked scripts window.location.reload(); } } }); }, saveSelectedConsent: function() { const categories = { analytics: document.getElementById('consent-analytics')?.checked || false, marketing: document.getElementById('consent-marketing')?.checked || false, functional: document.getElementById('consent-functional')?.checked || false }; this.saveConsent(categories); }, hideBanner: function() { const banner = document.getElementById('cookie-consent-banner'); if (banner) { banner.classList.add('hidden'); } } }; // Initialize when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => CookieConsent.init()); } else { CookieConsent.init(); } // Expose for external access window.CookieConsent = CookieConsent; })(); ``` ## Multi-Store and Multi-Language Configuration Both Magento and PrestaShop support multi-store setups. Cookie consent must be configured per store/language to comply with regional regulations. ### Magento 2 Multi-Website Configuration ```php 'eu_regulations', 'GB' => 'uk_regulations', 'US_CA' => 'ccpa_regulations', 'BR' => 'lgpd_regulations', 'default' => 'default_regulations', ]; public function __construct( StoreManagerInterface $storeManager, ScopeConfigInterface $scopeConfig ) { $this->storeManager = $storeManager; $this->scopeConfig = $scopeConfig; } public function getConsentConfig(): array { $storeId = $this->storeManager->getStore()->getId(); $region = $this->detectRegion(); $baseConfig = [ 'banner_enabled' => $this->scopeConfig->isSetFlag( 'cookie_consent/general/enabled', ScopeInterface::SCOPE_STORE, $storeId ), 'banner_position' => $this->scopeConfig->getValue( 'cookie_consent/general/position', ScopeInterface::SCOPE_STORE, $storeId ), 'consent_model' => $this->scopeConfig->getValue( 'cookie_consent/general/consent_model', ScopeInterface::SCOPE_STORE, $storeId ), ]; // Apply regional overrides return array_merge($baseConfig, $this->getRegionalConfig($region)); } private function getRegionalConfig(string $region): array { $configs = [ 'eu_regulations' => [ 'consent_model' => 'opt-in', 'show_reject_all' => true, 'tcf_enabled' => true, 'gcm_enabled' => true, 'default_analytics' => false, 'default_marketing' => false, ], 'uk_regulations' => [ 'consent_model' => 'opt-in', 'show_reject_all' => true, 'tcf_enabled' => true, 'gcm_enabled' => true, 'default_analytics' => false, 'default_marketing' => false, ], 'ccpa_regulations' => [ 'consent_model' => 'opt-out', 'show_reject_all' => true, 'show_do_not_sell' => true, 'tcf_enabled' => false, 'gcm_enabled' => true, 'default_analytics' => true, 'default_marketing' => true, ], 'lgpd_regulations' => [ 'consent_model' => 'opt-in', 'show_reject_all' => true, 'tcf_enabled' => false, 'gcm_enabled' => true, 'default_analytics' => false, 'default_marketing' => false, ], 'default_regulations' => [ 'consent_model' => 'opt-in', 'show_reject_all' => true, 'tcf_enabled' => false, 'gcm_enabled' => true, 'default_analytics' => false, 'default_marketing' => false, ], ]; return $configs[$region] ?? $configs['default_regulations']; } private function detectRegion(): string { // Implement GeoIP detection or use store configuration // This is a simplified example $storeCode = $this->storeManager->getStore()->getCode(); $storeRegionMap = [ 'eu_de' => 'eu_regulations', 'eu_fr' => 'eu_regulations', 'uk' => 'uk_regulations', 'us' => 'ccpa_regulations', 'br' => 'lgpd_regulations', ]; return $storeRegionMap[$storeCode] ?? 'default_regulations'; } } ``` ### PrestaShop Multi-Shop Configuration ```php shop->id; } // Get shop-specific configuration $config = [ 'enabled' => Configuration::get('COOKIE_CONSENT_ENABLED', null, null, $shopId), 'consent_model' => Configuration::get('COOKIE_CONSENT_MODEL', null, null, $shopId), 'tcf_enabled' => Configuration::get('COOKIE_CONSENT_TCF', null, null, $shopId), 'gcm_enabled' => Configuration::get('COOKIE_CONSENT_GCM', null, null, $shopId), 'banner_text' => Configuration::get('COOKIE_CONSENT_TEXT', null, null, $shopId), ]; // Get language-specific texts $languages = Language::getLanguages(true, $shopId); $config['texts'] = []; foreach ($languages as $lang) { $config['texts'][$lang['id_lang']] = [ 'banner_title' => Configuration::get( 'COOKIE_CONSENT_TITLE', $lang['id_lang'], null, $shopId ), 'banner_description' => Configuration::get( 'COOKIE_CONSENT_DESC', $lang['id_lang'], null, $shopId ), 'accept_button' => Configuration::get( 'COOKIE_CONSENT_ACCEPT', $lang['id_lang'], null, $shopId ), 'reject_button' => Configuration::get( 'COOKIE_CONSENT_REJECT', $lang['id_lang'], null, $shopId ), ]; } return $config; } public static function getRegionalRules($countryIso) { $rules = [ // EU Countries 'DE' => ['model' => 'opt-in', 'tcf' => true, 'strict' => true], 'FR' => ['model' => 'opt-in', 'tcf' => true, 'strict' => true], 'IT' => ['model' => 'opt-in', 'tcf' => true, 'strict' => true], 'ES' => ['model' => 'opt-in', 'tcf' => true, 'strict' => true], 'NL' => ['model' => 'opt-in', 'tcf' => true, 'strict' => true], // UK 'GB' => ['model' => 'opt-in', 'tcf' => true, 'strict' => true], // US States 'US' => ['model' => 'opt-out', 'tcf' => false, 'strict' => false], // Brazil 'BR' => ['model' => 'opt-in', 'tcf' => false, 'strict' => true], // Default 'default' => ['model' => 'opt-in', 'tcf' => false, 'strict' => false], ]; return $rules[$countryIso] ?? $rules['default']; } } ``` ## Testing Your Cookie Consent Implementation Thorough testing is critical for e-commerce cookie consent. A bug could either expose you to legal risk or break your checkout. ### Automated Testing Suite ```php dispatch('/'); $body = $this->getResponse()->getBody(); $this->assertStringContainsString('cookie-consent-banner', $body); $this->assertStringContainsString('Essential', $body); $this->assertStringContainsString('Analytics', $body); } /** * @magentoAppArea frontend */ public function testCheckoutWorksWithoutConsent() { // Ensure no consent cookie exists $this->getRequest()->setCookies([]); // Navigate to checkout $this->dispatch('/checkout/'); // Verify checkout page loads $body = $this->getResponse()->getBody(); $this->assertStringContainsString('checkout-container', $body); $this->assertEquals(200, $this->getResponse()->getStatusCode()); } /** * @magentoAppArea frontend */ public function testAnalyticsBlockedWithoutConsent() { $this->dispatch('/'); $body = $this->getResponse()->getBody(); // Google Analytics should not be present without consent $this->assertStringNotContainsString('google-analytics.com/analytics.js', $body); $this->assertStringNotContainsString('gtag(', $body); } /** * @magentoAppArea frontend * @magentoConfigFixture current_store google/analytics/active 1 */ public function testAnalyticsLoadedWithConsent() { // Set consent cookie $consent = json_encode([ 'essential' => true, 'analytics' => true, 'marketing' => false, 'timestamp' => time(), ]); $this->getRequest()->setCookies(['cookie_consent' => $consent]); $this->dispatch('/'); $body = $this->getResponse()->getBody(); // Now analytics should be present $this->assertStringContainsString('gtag', $body); } /** * @magentoAppArea frontend */ public function testConsentSaveEndpoint() { $this->getRequest()->setMethod('POST'); $this->getRequest()->setPostValue([ 'analytics' => '1', 'marketing' => '0', 'functional' => '1', ]); $this->dispatch('/cookie/consent/save'); $response = json_decode($this->getResponse()->getBody(), true); $this->assertTrue($response['success']); } } ``` ### Manual Testing Checklist | Test Case | Expected Result | Priority | |-----------|-----------------|----------| | New visitor sees banner | Banner displays immediately | Critical | | Add to cart without consent | Works correctly | Critical | | Complete checkout without consent | Full flow works | Critical | | Accept all cookies | Banner hides, analytics loads | High | | Reject all cookies | Banner hides, cookies deleted | High | | Essential cookies still work | Cart, session maintained | Critical | | Analytics blocked pre-consent | No GA calls in network tab | High | | Marketing blocked pre-consent | No FB pixel calls | High | | Consent persists across sessions | Cookie stored for 1 year | Medium | | Multi-store consent isolation | Separate consent per store | Medium | | Mobile banner usability | Touch-friendly, not covering content | High | | Cookie settings accessible | Link in footer works | Medium | ## Performance Optimization Cookie consent can impact page load times if not implemented carefully. ### Magento 2 Performance Tips ```javascript // Defer banner initialization until after critical content require(['jquery', 'domReady!'], function($) { // Wait for page to be interactive requestIdleCallback(function() { require(['cookieConsent'], function(CookieConsent) { CookieConsent.initialize(); }); }); }); ``` ```php getVisitorId(); $cached = $this->cache->load($cacheKey); if ($cached !== false) { return (bool) $cached; } $hasConsent = $this->consentManager->hasConsentFor($category); $this->cache->save( (string) (int) $hasConsent, $cacheKey, [self::CACHE_TAG], self::CACHE_LIFETIME ); return $hasConsent; } private function getVisitorId(): string { // Generate based on session or cookie return md5($_COOKIE['PHPSESSID'] ?? 'anonymous'); } } ``` ## Common Issues and Solutions ### Issue: Cart Empties After Consent **Cause:** Session cookie was accidentally categorized as non-essential. **Solution:** ```php // Ensure PHPSESSID is in essential category private const ESSENTIAL_COOKIES = [ 'PHPSESSID', 'form_key', // ... other essential cookies ]; public function shouldBlockCookie(string $name): bool { if (in_array($name, self::ESSENTIAL_COOKIES)) { return false; // Never block essential } // ... rest of logic } ``` ### Issue: Banner Keeps Reappearing **Cause:** Consent cookie path or domain mismatch. **Solution:** ```php // Ensure cookie path matches site structure $metadata = $this->cookieMetadataFactory ->createPublicCookieMetadata() ->setPath('/') // Must be root ->setDomain('.' . $this->getDomain()) // Include subdomain dot ->setHttpOnly(false) ->setSecure(true); ``` ### Issue: Third-Party Scripts Still Loading **Cause:** Scripts loaded before consent check runs. **Solution:** ```html ``` ## Key Takeaways Implementing cookie consent on Magento 2 and PrestaShop requires understanding the unique architectures of each platform. The key principles are: 1. **Never block essential cookies** - Cart, session, and security cookies must always work 2. **Intercept script loading** - Use RequireJS hooks (Magento) or script interception (PrestaShop) 3. **Test checkout thoroughly** - The purchase flow must work without any consent 4. **Configure per-store** - Multi-store setups need regional compliance rules 5. **Monitor performance** - Cookie consent shouldn't slow down your store By following this guide and using either commercial plugins or the custom implementations provided, you can achieve GDPR, CCPA, and ePrivacy compliance while maintaining an excellent shopping experience for your customers. Remember that cookie consent is not a one-time setup—you must continuously monitor for new cookies from third-party integrations and update your configuration accordingly.
D

David Kim, WordPress Developer

Contributing writer at GetCookies, specializing in privacy compliance, consent management, and digital marketing optimization.

Ready to Simplify Cookie Consent?

GetCookies makes GDPR, CCPA, and global privacy compliance effortless. Get started today.