name = 'gdprcookieconsent'; $this->tab = 'front_office_features'; $this->version = '1.0.1'; $this->author = 'Walzen665'; $this->need_instance = 0; $this->ps_versions_compliancy = [ 'min' => '1.7.0.0', 'max' => _PS_VERSION_ ]; $this->bootstrap = true; parent::__construct(); $this->displayName = $this->l('GDPR Cookie Consent'); $this->description = $this->l('Adds a GDPR compliant cookie consent modal to your shop'); $this->confirmUninstall = $this->l('Are you sure you want to uninstall?'); } /** * Install the module */ public function install() { return parent::install() && $this->registerHook('displayHeader') && $this->registerHook('displayFooter') && Configuration::updateValue('GDPR_COOKIE_ENABLED', 1) && Configuration::updateValue('GDPR_COOKIE_MESSAGE', 'This website uses cookies to ensure you get the best experience. We collect and process your data for website functionality, analytics, and personalized advertising.') && Configuration::updateValue('GDPR_COOKIE_ACCEPT', 'Accept All Cookies') && Configuration::updateValue('GDPR_COOKIE_DECLINE', 'Decline Non-Essential') && Configuration::updateValue('GDPR_COOKIE_SETTINGS', 'Cookie Settings') && Configuration::updateValue('GDPR_COOKIE_MORE_INFO', 'More Information') && Configuration::updateValue('GDPR_COOKIE_MORE_INFO_URL', 'https://yourstore.net/content/privacy-policy') && Configuration::updateValue('GDPR_COOKIE_DATA_CONTROLLER', 'Your Company Name') && Configuration::updateValue('GDPR_COOKIE_RETENTION_PERIOD', '365 days') && Configuration::updateValue('GDPR_COOKIE_THIRD_PARTIES', 'Google Analytics, Facebook, etc.') && Configuration::updateValue('GDPR_COOKIE_MANAGE_TEXT', 'Manage Cookie Preferences') && Configuration::updateValue('GDPR_COOKIE_ONLY_REQUIRED', 1) && Configuration::updateValue('GDPR_COOKIE_NECESSARY_DESC', 'Necessary cookies help make a website usable by enabling basic functions like page navigation and access to secure areas. The website cannot function properly without these cookies.') && Configuration::updateValue('GDPR_COOKIE_FUNCTIONAL_DESC', 'Functional cookies enable a website to remember information that changes the way the website behaves or looks, like your preferred language or the region you are in.') && Configuration::updateValue('GDPR_COOKIE_ANALYTICS_DESC', 'Analytics cookies help website owners understand how visitors interact with websites by collecting and reporting information anonymously.') && Configuration::updateValue('GDPR_COOKIE_MARKETING_DESC', 'Marketing cookies are used to track visitors across websites. The intention is to display ads that are relevant and engaging for the individual user.'); } /** * Uninstall the module */ public function uninstall() { return parent::uninstall() && Configuration::deleteByName('GDPR_COOKIE_ENABLED') && Configuration::deleteByName('GDPR_COOKIE_MESSAGE') && Configuration::deleteByName('GDPR_COOKIE_ACCEPT') && Configuration::deleteByName('GDPR_COOKIE_DECLINE') && Configuration::deleteByName('GDPR_COOKIE_SETTINGS') && Configuration::deleteByName('GDPR_COOKIE_MORE_INFO') && Configuration::deleteByName('GDPR_COOKIE_MORE_INFO_URL') && Configuration::deleteByName('GDPR_COOKIE_DATA_CONTROLLER') && Configuration::deleteByName('GDPR_COOKIE_RETENTION_PERIOD') && Configuration::deleteByName('GDPR_COOKIE_THIRD_PARTIES') && Configuration::deleteByName('GDPR_COOKIE_MANAGE_TEXT') && Configuration::deleteByName('GDPR_COOKIE_ONLY_REQUIRED') && Configuration::deleteByName('GDPR_COOKIE_NECESSARY_DESC') && Configuration::deleteByName('GDPR_COOKIE_FUNCTIONAL_DESC') && Configuration::deleteByName('GDPR_COOKIE_ANALYTICS_DESC') && Configuration::deleteByName('GDPR_COOKIE_MARKETING_DESC'); } /** * Load the configuration form */ public function getContent() { $output = ''; // If form submitted if (Tools::isSubmit('submitGdprCookieModule')) { // Get configuration values from form $enabled = (int)Tools::getValue('GDPR_COOKIE_ENABLED'); $message = Tools::getValue('GDPR_COOKIE_MESSAGE'); $accept = Tools::getValue('GDPR_COOKIE_ACCEPT'); $decline = Tools::getValue('GDPR_COOKIE_DECLINE'); $settings = Tools::getValue('GDPR_COOKIE_SETTINGS'); $moreInfo = Tools::getValue('GDPR_COOKIE_MORE_INFO'); $moreInfoUrl = Tools::getValue('GDPR_COOKIE_MORE_INFO_URL'); $dataController = Tools::getValue('GDPR_COOKIE_DATA_CONTROLLER'); $retentionPeriod = Tools::getValue('GDPR_COOKIE_RETENTION_PERIOD'); $thirdParties = Tools::getValue('GDPR_COOKIE_THIRD_PARTIES'); $manageText = Tools::getValue('GDPR_COOKIE_MANAGE_TEXT'); $onlyRequired = Tools::getValue('GDPR_COOKIE_ONLY_REQUIRED'); $necessaryDesc = Tools::getValue('GDPR_COOKIE_NECESSARY_DESC'); $functionalDesc = Tools::getValue('GDPR_COOKIE_FUNCTIONAL_DESC'); $analyticsDesc = Tools::getValue('GDPR_COOKIE_ANALYTICS_DESC'); $marketingDesc = Tools::getValue('GDPR_COOKIE_MARKETING_DESC'); // Update configuration values Configuration::updateValue('GDPR_COOKIE_ENABLED', $enabled); Configuration::updateValue('GDPR_COOKIE_MESSAGE', $message); Configuration::updateValue('GDPR_COOKIE_ACCEPT', $accept); Configuration::updateValue('GDPR_COOKIE_DECLINE', $decline); Configuration::updateValue('GDPR_COOKIE_SETTINGS', $settings); Configuration::updateValue('GDPR_COOKIE_MORE_INFO', $moreInfo); Configuration::updateValue('GDPR_COOKIE_MORE_INFO_URL', $moreInfoUrl); Configuration::updateValue('GDPR_COOKIE_DATA_CONTROLLER', $dataController); Configuration::updateValue('GDPR_COOKIE_RETENTION_PERIOD', $retentionPeriod); Configuration::updateValue('GDPR_COOKIE_THIRD_PARTIES', $thirdParties); Configuration::updateValue('GDPR_COOKIE_MANAGE_TEXT', $manageText); Configuration::updateValue('GDPR_COOKIE_ONLY_REQUIRED', $onlyRequired); Configuration::updateValue('GDPR_COOKIE_NECESSARY_DESC', $necessaryDesc); Configuration::updateValue('GDPR_COOKIE_FUNCTIONAL_DESC', $functionalDesc); Configuration::updateValue('GDPR_COOKIE_ANALYTICS_DESC', $analyticsDesc); Configuration::updateValue('GDPR_COOKIE_MARKETING_DESC', $marketingDesc); // Display confirmation $output .= $this->displayConfirmation($this->l('Settings updated')); } // Display the configuration form return $output . $this->displayForm(); } /** * Create the configuration form */ protected function displayForm() { // Init Fields form array $form = [ 'form' => [ 'legend' => [ 'title' => $this->l('Settings'), 'icon' => 'icon-cogs', ], 'input' => [ [ 'type' => 'switch', 'label' => $this->l('Enable Cookie Consent'), 'name' => 'GDPR_COOKIE_ENABLED', 'is_bool' => true, 'values' => [ [ 'id' => 'active_on', 'value' => 1, 'label' => $this->l('Enabled') ], [ 'id' => 'active_off', 'value' => 0, 'label' => $this->l('Disabled') ] ], ], [ 'type' => 'textarea', 'label' => $this->l('Cookie Consent Message'), 'name' => 'GDPR_COOKIE_MESSAGE', 'required' => true, ], [ 'type' => 'text', 'label' => $this->l('Data Controller'), 'name' => 'GDPR_COOKIE_DATA_CONTROLLER', 'desc' => $this->l('Your company/organization name'), 'required' => true, ], [ 'type' => 'text', 'label' => $this->l('Cookie Retention Period'), 'name' => 'GDPR_COOKIE_RETENTION_PERIOD', 'desc' => $this->l('How long cookies will be stored (e.g., 365 days)'), 'required' => true, ], [ 'type' => 'textarea', 'label' => $this->l('Third-Party Recipients'), 'name' => 'GDPR_COOKIE_THIRD_PARTIES', 'desc' => $this->l('List third parties that receive cookie data'), 'required' => true, ], [ 'type' => 'text', 'label' => $this->l('Accept Button Text'), 'name' => 'GDPR_COOKIE_ACCEPT', 'required' => true, ], [ 'type' => 'text', 'label' => $this->l('Decline Button Text'), 'name' => 'GDPR_COOKIE_DECLINE', 'required' => true, ], [ 'type' => 'text', 'label' => $this->l('Settings Button Text'), 'name' => 'GDPR_COOKIE_SETTINGS', 'required' => true, ], [ 'type' => 'text', 'label' => $this->l('Manage Preferences Text'), 'name' => 'GDPR_COOKIE_MANAGE_TEXT', 'desc' => $this->l('Text for the manage preferences button (displayed after consent is given)'), 'required' => true, ], [ 'type' => 'text', 'label' => $this->l('More Info Button Text'), 'name' => 'GDPR_COOKIE_MORE_INFO', 'required' => true, ], [ 'type' => 'text', 'label' => $this->l('More Info URL'), 'desc' => $this->l('URL to your Privacy Policy page'), 'name' => 'GDPR_COOKIE_MORE_INFO_URL', 'required' => true, ], [ 'type' => 'switch', 'label' => $this->l('This cookie types are used'), 'name' => 'GDPR_COOKIE_ONLY_REQUIRED', 'desc' => $this->l('If this option is enabled, no config modal will be rendered and there will only be a single button to hide the cookie notice. (Only enable this, if you don\'t track any user data)'), 'is_bool' => true, 'required' => true, 'values' => [ [ 'id' => 'active_on', 'value' => 1, 'label' => $this->l('Nessessary only') ], [ 'id' => 'active_off', 'value' => 0, 'label' => $this->l('All cookies') ] ], ], [ 'type' => 'textarea', 'label' => $this->l('Necessary Cookies Description'), 'name' => 'GDPR_COOKIE_NECESSARY_DESC', 'desc' => $this->l('Description for necessary cookies shown in the modal'), 'required' => true, ], [ 'type' => 'textarea', 'label' => $this->l('Functional Cookies Description'), 'name' => 'GDPR_COOKIE_FUNCTIONAL_DESC', 'desc' => $this->l('Description for functional cookies shown in the modal'), 'required' => true, ], [ 'type' => 'textarea', 'label' => $this->l('Analytics Cookies Description'), 'name' => 'GDPR_COOKIE_ANALYTICS_DESC', 'desc' => $this->l('Description for analytics cookies shown in the modal'), 'required' => true, ], [ 'type' => 'textarea', 'label' => $this->l('Marketing Cookies Description'), 'name' => 'GDPR_COOKIE_MARKETING_DESC', 'desc' => $this->l('Description for marketing cookies shown in the modal'), 'required' => true, ], ], 'submit' => [ 'title' => $this->l('Save'), 'class' => 'btn btn-default pull-right', ], ], ]; $helper = new HelperForm(); // Module, token and currentIndex $helper->module = $this; $helper->name_controller = $this->name; $helper->token = Tools::getAdminTokenLite('AdminModules'); $helper->currentIndex = AdminController::$currentIndex . '&configure=' . $this->name; // Language $helper->default_form_language = $this->context->language->id; $helper->allow_employee_form_lang = Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG', 0); // Title and toolbar $helper->title = $this->displayName; $helper->show_toolbar = true; $helper->toolbar_scroll = true; $helper->submit_action = 'submitGdprCookieModule'; // Load current values $helper->fields_value['GDPR_COOKIE_ENABLED'] = Configuration::get('GDPR_COOKIE_ENABLED'); $helper->fields_value['GDPR_COOKIE_MESSAGE'] = Configuration::get('GDPR_COOKIE_MESSAGE'); $helper->fields_value['GDPR_COOKIE_ACCEPT'] = Configuration::get('GDPR_COOKIE_ACCEPT'); $helper->fields_value['GDPR_COOKIE_DECLINE'] = Configuration::get('GDPR_COOKIE_DECLINE'); $helper->fields_value['GDPR_COOKIE_SETTINGS'] = Configuration::get('GDPR_COOKIE_SETTINGS'); $helper->fields_value['GDPR_COOKIE_MORE_INFO'] = Configuration::get('GDPR_COOKIE_MORE_INFO'); $helper->fields_value['GDPR_COOKIE_MORE_INFO_URL'] = Configuration::get('GDPR_COOKIE_MORE_INFO_URL'); $helper->fields_value['GDPR_COOKIE_DATA_CONTROLLER'] = Configuration::get('GDPR_COOKIE_DATA_CONTROLLER'); $helper->fields_value['GDPR_COOKIE_RETENTION_PERIOD'] = Configuration::get('GDPR_COOKIE_RETENTION_PERIOD'); $helper->fields_value['GDPR_COOKIE_THIRD_PARTIES'] = Configuration::get('GDPR_COOKIE_THIRD_PARTIES'); $helper->fields_value['GDPR_COOKIE_MANAGE_TEXT'] = Configuration::get('GDPR_COOKIE_MANAGE_TEXT'); $helper->fields_value['GDPR_COOKIE_ONLY_REQUIRED'] = Configuration::get('GDPR_COOKIE_ONLY_REQUIRED'); $helper->fields_value['GDPR_COOKIE_NECESSARY_DESC'] = Configuration::get('GDPR_COOKIE_NECESSARY_DESC'); $helper->fields_value['GDPR_COOKIE_FUNCTIONAL_DESC'] = Configuration::get('GDPR_COOKIE_FUNCTIONAL_DESC'); $helper->fields_value['GDPR_COOKIE_ANALYTICS_DESC'] = Configuration::get('GDPR_COOKIE_ANALYTICS_DESC'); $helper->fields_value['GDPR_COOKIE_MARKETING_DESC'] = Configuration::get('GDPR_COOKIE_MARKETING_DESC'); return $helper->generateForm([$form]); } /** * Add CSS and JS to the header */ public function hookDisplayHeader() { if (!Configuration::get('GDPR_COOKIE_ENABLED')) { return; } // Add CSS $this->context->controller->addCSS($this->_path . 'views/css/gdpr_cookie.css'); // Add JS $this->context->controller->addJS($this->_path . 'views/js/gdpr_cookie.js'); // Add JS variables for modal Media::addJsDef([ 'gdprCookieMessage' => Configuration::get('GDPR_COOKIE_MESSAGE'), 'gdprCookieAccept' => Configuration::get('GDPR_COOKIE_ACCEPT'), 'gdprCookieDecline' => Configuration::get('GDPR_COOKIE_DECLINE'), 'gdprCookieSettings' => Configuration::get('GDPR_COOKIE_SETTINGS'), 'gdprCookieMoreInfo' => Configuration::get('GDPR_COOKIE_MORE_INFO'), 'gdprCookieMoreInfoUrl' => Configuration::get('GDPR_COOKIE_MORE_INFO_URL'), 'gdprCookieDataController' => Configuration::get('GDPR_COOKIE_DATA_CONTROLLER', ''), 'gdprCookieRetentionPeriod' => Configuration::get('GDPR_COOKIE_RETENTION_PERIOD', '365 days'), 'gdprCookieThirdParties' => Configuration::get('GDPR_COOKIE_THIRD_PARTIES', ''), 'gdprCookieManageText' => Configuration::get('GDPR_COOKIE_MANAGE_TEXT', 'Manage Cookies'), 'gdprCookieOnlyRequired' => Configuration::get('GDPR_COOKIE_ONLY_REQUIRED'), ]); // Assign variables to Smarty for the manage button template $this->context->smarty->assign([ 'gdprCookieManageText' => Configuration::get('GDPR_COOKIE_MANAGE_TEXT', 'Manage Cookies'), ]); // If not in required-only mode, add script for tagging known third-party scripts if (!Configuration::get('GDPR_COOKIE_ONLY_REQUIRED')) { $this->tagThirdPartyScripts(); } // Return the template content - but don't throw an error if it doesn't exist yet if (file_exists(_PS_MODULE_DIR_ . $this->name . '/views/templates/hook/manage_button.tpl')) { return $this->display(__FILE__, 'views/templates/hook/manage_button.tpl'); } } /** * Add the cookie modal to the footer */ public function hookDisplayFooter() { if (!Configuration::get('GDPR_COOKIE_ENABLED')) { return; } $this->smarty->assign([ 'gdprCookieMessage' => Configuration::get('GDPR_COOKIE_MESSAGE'), 'gdprCookieAccept' => Configuration::get('GDPR_COOKIE_ACCEPT'), 'gdprCookieDecline' => Configuration::get('GDPR_COOKIE_DECLINE'), 'gdprCookieSettings' => Configuration::get('GDPR_COOKIE_SETTINGS'), 'gdprCookieMoreInfo' => Configuration::get('GDPR_COOKIE_MORE_INFO'), 'gdprCookieMoreInfoUrl' => Configuration::get('GDPR_COOKIE_MORE_INFO_URL'), 'gdprCookieDataController' => Configuration::get('GDPR_COOKIE_DATA_CONTROLLER'), 'gdprCookieRetentionPeriod' => Configuration::get('GDPR_COOKIE_RETENTION_PERIOD'), 'gdprCookieThirdParties' => Configuration::get('GDPR_COOKIE_THIRD_PARTIES'), 'gdprCookieManageText' => Configuration::get('GDPR_COOKIE_MANAGE_TEXT'), 'gdprCookieOnlyRequired' => Configuration::get('GDPR_COOKIE_ONLY_REQUIRED'), 'gdprCookieNecessaryDesc' => Configuration::get('GDPR_COOKIE_NECESSARY_DESC'), 'gdprCookieFunctionalDesc' => Configuration::get('GDPR_COOKIE_FUNCTIONAL_DESC'), 'gdprCookieAnalyticsDesc' => Configuration::get('GDPR_COOKIE_ANALYTICS_DESC'), 'gdprCookieMarketingDesc' => Configuration::get('GDPR_COOKIE_MARKETING_DESC'), ]); return $this->display(__FILE__, 'views/templates/hook/footer.tpl'); } /** * Helper function to tag third-party scripts with appropriate consent categories */ protected function tagThirdPartyScripts() { // Require the script detector class require_once(dirname(__FILE__).'/classes/GdprScriptDetector.php'); // Get PrestaShop's currently registered JS files $jsFiles = $this->context->controller->js_files; // Loop through JS files and add consent attributes based on patterns foreach ($jsFiles as $key => $jsFile) { // Use the detector class $category = GdprScriptDetector::detectCategory($jsFile); // Add attribute to the script $this->context->smarty->assign([ 'js_' . md5($jsFile) . '_attributes' => 'data-cookieconsent="' . $category . '"' ]); } // Inject a helper script to tag inline scripts as well $this->context->controller->registerJavascript( 'gdpr-cookie-helper', $this->_path . 'views/js/gdpr_cookie_helper.js', ['position' => 'head', 'priority' => 1] ); } /** * Modifies scripts in the HTML head */ public function hookActionHtmlHeadFooter($params) { if (!Configuration::get('GDPR_COOKIE_ENABLED') || Configuration::get('GDPR_COOKIE_ONLY_REQUIRED')) { return; } // Get the current HTML content $html = $params['html_content']; // Modify script tags to add data-cookieconsent attribute $patterns = [ // Google Analytics pattern '/]*)(gtag|googletagmanager|google-analytics)([^>]*)>/' => '', // Facebook Pixel pattern '/]*)(connect\.facebook\.net|fbevents\.js)([^>]*)>/' => '', // Generic analytics patterns '/]*)(analytics|piwik|matomo|stats)([^>]*)>/' => '', // Marketing patterns '/]*)(ads|adsbygoogle|doubleclick|googlesyndication)([^>]*)>/' => '', // Functional patterns (more conservative, as these might be necessary) '/]*)(recaptcha|chat)([^>]*)>/' => '', ]; foreach ($patterns as $pattern => $replacement) { $html = preg_replace($pattern, $replacement, $html); } // Update the HTML content $params['html_content'] = $html; } }