Advanced third party cookie manager
This commit is contained in:
211
views/js/gdpr_cookie_helper.js
Normal file
211
views/js/gdpr_cookie_helper.js
Normal file
@@ -0,0 +1,211 @@
|
||||
/**
|
||||
* GDPR Cookie Consent Helper for PrestaShop
|
||||
*
|
||||
* @author Walzen665
|
||||
* @copyright Copyright (c) 2025
|
||||
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
|
||||
*/
|
||||
|
||||
// This script runs early in the page load to tag inline scripts with appropriate consent categories
|
||||
(function() {
|
||||
// Known script patterns to identify analytics, marketing and functional scripts
|
||||
const scriptPatterns = {
|
||||
analytics: [
|
||||
/google[\s\-_]?analytics/i,
|
||||
/ga\s*\(\s*['"]create/i,
|
||||
/googletagmanager/i,
|
||||
/gtag/i,
|
||||
/\_gaq/i,
|
||||
/matomo/i,
|
||||
/piwik/i,
|
||||
/mixpanel/i,
|
||||
/hotjar/i,
|
||||
/clarity/i
|
||||
],
|
||||
marketing: [
|
||||
/facebook[\s\-_]?pixel/i,
|
||||
/fbq\s*\(\s*['"]init/i,
|
||||
/doubleclick/i,
|
||||
/adwords/i,
|
||||
/google[\s\-_]?ad[\s\-_]?services/i,
|
||||
/google[\s\-_]?tag[\s\-_]?manager/i,
|
||||
/gtm/i,
|
||||
/twitter[\s\-_]?pixel/i,
|
||||
/pinterest[\s\-_]?tag/i
|
||||
],
|
||||
functional: [
|
||||
/recaptcha/i,
|
||||
/chat/i,
|
||||
/livechat/i,
|
||||
/support/i,
|
||||
/feedback/i,
|
||||
/preference/i,
|
||||
/usercentrics/i
|
||||
]
|
||||
};
|
||||
|
||||
// Function to process and tag a script element
|
||||
function processScript(script) {
|
||||
// Skip if it already has a consent attribute
|
||||
if (script.hasAttribute('data-cookieconsent')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip our own scripts
|
||||
if (script.src && script.src.indexOf('gdpr_cookie') !== -1) {
|
||||
script.setAttribute('data-cookieconsent', 'necessary');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check content for patterns
|
||||
const content = script.innerHTML || '';
|
||||
const src = script.src || '';
|
||||
|
||||
// Determine script category
|
||||
let category = 'necessary'; // Default category
|
||||
|
||||
for (const [cat, patterns] of Object.entries(scriptPatterns)) {
|
||||
for (const pattern of patterns) {
|
||||
if (pattern.test(content) || pattern.test(src)) {
|
||||
category = cat;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (category !== 'necessary') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Tag the script
|
||||
script.setAttribute('data-cookieconsent', category);
|
||||
|
||||
// For non-necessary scripts, we'll create a duplicate with the correct attribute
|
||||
// but disabled until consent is given
|
||||
if (category !== 'necessary') {
|
||||
const originalScript = script;
|
||||
const newScript = document.createElement('script');
|
||||
|
||||
// Copy attributes
|
||||
Array.from(originalScript.attributes).forEach(attr => {
|
||||
if (attr.name !== 'data-cookieconsent') {
|
||||
newScript.setAttribute(attr.name, attr.value);
|
||||
}
|
||||
});
|
||||
|
||||
// Set consent attribute
|
||||
newScript.setAttribute('data-cookieconsent', category);
|
||||
|
||||
// Copy content if it's an inline script
|
||||
if (!originalScript.src && originalScript.innerHTML) {
|
||||
newScript.innerHTML = originalScript.innerHTML;
|
||||
}
|
||||
|
||||
// Replace the original script
|
||||
originalScript.parentNode.replaceChild(newScript, originalScript);
|
||||
|
||||
// Prevent execution by removing src and content
|
||||
newScript.removeAttribute('src');
|
||||
newScript.innerHTML = '';
|
||||
}
|
||||
}
|
||||
|
||||
// Process existing scripts
|
||||
document.querySelectorAll('script').forEach(processScript);
|
||||
|
||||
// Use a MutationObserver to catch dynamically added scripts
|
||||
const observer = new MutationObserver(mutations => {
|
||||
mutations.forEach(mutation => {
|
||||
mutation.addedNodes.forEach(node => {
|
||||
if (node.tagName === 'SCRIPT') {
|
||||
processScript(node);
|
||||
} else if (node.querySelectorAll) {
|
||||
node.querySelectorAll('script').forEach(processScript);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Start observing the document
|
||||
observer.observe(document.documentElement, {
|
||||
childList: true,
|
||||
subtree: true
|
||||
});
|
||||
|
||||
// Also process iframes
|
||||
function processIframe(iframe) {
|
||||
// Skip if it already has a consent attribute
|
||||
if (iframe.hasAttribute('data-cookieconsent')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const src = iframe.src || '';
|
||||
|
||||
// Common third-party iframe sources
|
||||
const iframePatterns = {
|
||||
marketing: [
|
||||
/youtube/i,
|
||||
/vimeo/i,
|
||||
/facebook\.com\/plugins/i,
|
||||
/twitter\.com\/widgets/i,
|
||||
/instagram\.com/i,
|
||||
/pinterest\.com/i,
|
||||
/doubleclick/i,
|
||||
/ads/i
|
||||
],
|
||||
analytics: [
|
||||
/googletagmanager/i,
|
||||
/analytics/i
|
||||
],
|
||||
functional: [
|
||||
/recaptcha/i,
|
||||
/maps\.google/i,
|
||||
/google\.com\/maps/i,
|
||||
/disqus/i,
|
||||
/livechat/i,
|
||||
/chat/i
|
||||
]
|
||||
};
|
||||
|
||||
// Determine iframe category
|
||||
let category = 'necessary'; // Default category
|
||||
|
||||
for (const [cat, patterns] of Object.entries(iframePatterns)) {
|
||||
for (const pattern of patterns) {
|
||||
if (pattern.test(src)) {
|
||||
category = cat;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (category !== 'necessary') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Tag the iframe
|
||||
iframe.setAttribute('data-cookieconsent', category);
|
||||
}
|
||||
|
||||
// Process existing iframes
|
||||
document.querySelectorAll('iframe').forEach(processIframe);
|
||||
|
||||
// Use the observer to catch dynamically added iframes
|
||||
const iframeObserver = new MutationObserver(mutations => {
|
||||
mutations.forEach(mutation => {
|
||||
mutation.addedNodes.forEach(node => {
|
||||
if (node.tagName === 'IFRAME') {
|
||||
processIframe(node);
|
||||
} else if (node.querySelectorAll) {
|
||||
node.querySelectorAll('iframe').forEach(processIframe);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Start observing for iframes
|
||||
iframeObserver.observe(document.documentElement, {
|
||||
childList: true,
|
||||
subtree: true
|
||||
});
|
||||
})();
|
Reference in New Issue
Block a user