Files
Websites/Profice WebSite backup/scripts/cookie-consent.js
2026-01-30 10:48:56 +01:00

424 lines
15 KiB
JavaScript

/**
* Cookie Consent Management System
* All sensitive data (tracking IDs, URLs) are loaded from server-side PHP
* Includes fallback for local file access (no server)
*
* @version 2.1.0
*/
document.addEventListener('DOMContentLoaded', function() {
// ==========================================
// CONFIGURATION
// ==========================================
const cookieCategories = ['necessary', 'analytics', 'marketing'];
const API_ENDPOINT = 'scripts/add/send.php';
// Detect if running from file:// protocol (no server)
const isLocalFile = window.location.protocol === 'file:';
let consentState = {
hasConsented: false,
preferences: {}
};
let previousPreferences = {};
let trackingScripts = {};
// ==========================================
// DATALAYER INTEGRATION
// ==========================================
window.dataLayer = window.dataLayer || [];
function pushConsentToDataLayer(preferences) {
window.dataLayer.push({
'event': 'consent_update',
'consent': {
'analytics_storage': preferences.analytics ? 'granted' : 'denied',
'ad_storage': preferences.marketing ? 'granted' : 'denied',
'functionality_storage': preferences.necessary ? 'granted' : 'denied',
'personalization_storage': preferences.marketing ? 'granted' : 'denied',
'security_storage': 'granted'
}
});
}
function setDefaultConsent() {
window.dataLayer.push({
'event': 'consent_default',
'consent': {
'analytics_storage': 'denied',
'ad_storage': 'denied',
'functionality_storage': 'granted',
'personalization_storage': 'denied',
'security_storage': 'granted',
'wait_for_update': 500
}
});
}
// ==========================================
// STORAGE (API + LOCALSTORAGE FALLBACK)
// ==========================================
async function saveConsentToStorage(preferences) {
// Always save to localStorage as backup
const consentData = {
hasConsented: true,
preferences: preferences,
timestamp: new Date().toISOString()
};
localStorage.setItem('cookieConsent', JSON.stringify(consentData));
// Try API if not local file
if (!isLocalFile) {
try {
const response = await fetch(API_ENDPOINT, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ type: 'cookie_consent', preferences })
});
const result = await response.json();
if (result.success && result.data && result.data.scripts) {
trackingScripts = result.data.scripts;
}
return result.success;
} catch (e) {
// API failed, localStorage already saved
return false;
}
}
return true;
}
async function getConsentFromStorage() {
// Try localStorage first (faster)
const localConsent = localStorage.getItem('cookieConsent');
if (localConsent) {
try {
return JSON.parse(localConsent);
} catch (e) {
localStorage.removeItem('cookieConsent');
}
}
// Try API if not local file
if (!isLocalFile) {
try {
const response = await fetch(API_ENDPOINT, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ type: 'get_cookie_consent' })
});
const result = await response.json();
if (result.success && result.data) {
if (result.data.scripts) {
trackingScripts = result.data.scripts;
}
// Cache in localStorage
localStorage.setItem('cookieConsent', JSON.stringify(result.data));
return result.data;
}
} catch (e) {
// API unavailable
}
}
return null;
}
// ==========================================
// SCRIPT LOADING
// ==========================================
function loadTrackingScripts() {
if (!trackingScripts || Object.keys(trackingScripts).length === 0) return;
if (trackingScripts.ga && consentState.preferences.analytics) {
loadGoogleAnalytics(trackingScripts.ga);
}
if (trackingScripts.gtm && consentState.preferences.analytics) {
loadGTM(trackingScripts.gtm);
}
if (trackingScripts.fb && consentState.preferences.marketing) {
loadFacebookPixel(trackingScripts.fb);
}
if (trackingScripts.gads && consentState.preferences.marketing) {
loadGoogleAds(trackingScripts.gads);
}
if (trackingScripts.linkedin && consentState.preferences.marketing) {
loadLinkedIn(trackingScripts.linkedin);
}
}
function loadScript(src, callback) {
const script = document.createElement('script');
script.src = src;
script.async = true;
if (callback) script.onload = callback;
document.head.appendChild(script);
}
function loadGoogleAnalytics(config) {
if (!config.src || !config.config || !config.config.id) return;
loadScript(config.src, function() {
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
window.gtag = gtag;
gtag('js', new Date());
gtag('config', config.config.id);
});
}
function loadGTM(config) {
if (!config.id) return;
(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',config.id);
}
function loadFacebookPixel(config) {
if (!config.id) return;
!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,
document,'script','https://connect.facebook.net/en_US/fbevents.js');
fbq('init', config.id);
fbq('track', 'PageView');
}
function loadGoogleAds(config) {
if (!config.id) return;
loadScript('https://www.googletagmanager.com/gtag/js?id=' + config.id, function() {
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', config.id);
});
}
function loadLinkedIn(config) {
if (!config.id) return;
window._linkedin_partner_id = config.id;
window._linkedin_data_partner_ids = window._linkedin_data_partner_ids || [];
window._linkedin_data_partner_ids.push(config.id);
loadScript('https://snap.licdn.com/li.lms-analytics/insight.min.js');
}
// ==========================================
// COOKIE DELETION
// ==========================================
const cookiePatterns = {
analytics: ['_ga', '_gid', '_gat', '__utma', '__utmb', '__utmc', '__utmz'],
marketing: ['_fbp', '_fbc', 'fr', '_gcl_au', '_gcl_aw', 'IDE', 'DSID', 'NID']
};
function deleteCookie(name) {
const paths = ['/', window.location.pathname];
const domains = ['', window.location.hostname, '.' + window.location.hostname];
paths.forEach(path => {
domains.forEach(domain => {
document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=${path}${domain ? '; domain=' + domain : ''}`;
});
});
}
function deleteCookiesForCategory(category) {
const patterns = cookiePatterns[category] || [];
const allCookies = document.cookie.split(';');
allCookies.forEach(cookie => {
const cookieName = cookie.split('=')[0].trim();
patterns.forEach(pattern => {
if (cookieName.startsWith(pattern)) {
deleteCookie(cookieName);
}
});
});
}
function handlePreferenceChanges(newPreferences) {
Object.keys(cookiePatterns).forEach(category => {
if (previousPreferences[category] === true && newPreferences[category] === false) {
deleteCookiesForCategory(category);
window.dataLayer.push({ 'event': 'consent_revoked', 'consent_category': category });
}
});
previousPreferences = { ...newPreferences };
}
// ==========================================
// DOM ELEMENTS
// ==========================================
const cookieBanner = document.getElementById('cookieBanner');
const cookieModal = document.getElementById('cookieModal');
const acceptAllBtn = document.getElementById('cookieAcceptAll');
const rejectAllBtn = document.getElementById('cookieRejectAll');
const settingsBtn = document.getElementById('cookieSettings');
const modalCloseBtn = document.getElementById('cookieModalClose');
const savePreferencesBtn = document.getElementById('cookieSavePreferences');
// ==========================================
// CORE FUNCTIONS
// ==========================================
async function initCookieConsent() {
setDefaultConsent();
const savedConsent = await getConsentFromStorage();
if (savedConsent && savedConsent.hasConsented) {
consentState = {
hasConsented: true,
preferences: savedConsent.preferences || {}
};
previousPreferences = { ...consentState.preferences };
applyConsentPreferences();
return;
}
// Show banner after short delay
setTimeout(() => {
if (cookieBanner) cookieBanner.classList.add('show');
}, 500);
}
function applyConsentPreferences() {
pushConsentToDataLayer(consentState.preferences);
loadTrackingScripts();
window.dispatchEvent(new CustomEvent('cookieConsentUpdated', { detail: consentState.preferences }));
}
async function saveConsent(preferences) {
handlePreferenceChanges(preferences);
await saveConsentToStorage(preferences);
consentState = {
hasConsented: true,
preferences: preferences,
timestamp: new Date().toISOString()
};
applyConsentPreferences();
}
function hideBanner() {
if (cookieBanner) cookieBanner.classList.remove('show');
}
function showSettingsModal() {
if (cookieModal) {
cookieModal.classList.add('show');
populateSettingsModal();
}
}
function hideSettingsModal() {
if (cookieModal) cookieModal.classList.remove('show');
}
function populateSettingsModal() {
cookieCategories.forEach(key => {
const toggle = document.getElementById(`cookie-toggle-${key}`);
if (!toggle) return;
const isEnabled = consentState.preferences[key] || false;
const isRequired = key === 'necessary';
if (isRequired) {
toggle.classList.add('active', 'disabled');
toggle.setAttribute('aria-checked', 'true');
toggle.setAttribute('aria-disabled', 'true');
} else {
toggle.classList.toggle('active', isEnabled);
toggle.setAttribute('aria-checked', isEnabled ? 'true' : 'false');
toggle.onclick = () => {
toggle.classList.toggle('active');
toggle.setAttribute('aria-checked', toggle.classList.contains('active') ? 'true' : 'false');
};
}
});
}
function getModalPreferences() {
const preferences = {};
cookieCategories.forEach(key => {
const toggle = document.getElementById(`cookie-toggle-${key}`);
preferences[key] = key === 'necessary' ? true : (toggle ? toggle.classList.contains('active') : false);
});
return preferences;
}
// ==========================================
// EVENT LISTENERS
// ==========================================
if (acceptAllBtn) {
acceptAllBtn.addEventListener('click', () => {
const preferences = {};
cookieCategories.forEach(key => preferences[key] = true);
saveConsent(preferences);
hideBanner();
});
}
if (rejectAllBtn) {
rejectAllBtn.addEventListener('click', () => {
saveConsent({ necessary: true, analytics: false, marketing: false });
hideBanner();
});
}
if (settingsBtn) {
settingsBtn.addEventListener('click', showSettingsModal);
}
if (modalCloseBtn) {
modalCloseBtn.addEventListener('click', hideSettingsModal);
}
if (savePreferencesBtn) {
savePreferencesBtn.addEventListener('click', () => {
saveConsent(getModalPreferences());
hideSettingsModal();
hideBanner();
});
}
if (cookieModal) {
cookieModal.addEventListener('click', (e) => {
if (e.target === cookieModal) hideSettingsModal();
});
}
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && cookieModal && cookieModal.classList.contains('show')) {
hideSettingsModal();
}
});
// ==========================================
// PUBLIC API
// ==========================================
window.CookieConsent = {
getConsent: () => consentState,
hasConsent: (category) => consentState.preferences[category] === true,
updateConsent: saveConsent,
showSettings: showSettingsModal
};
// ==========================================
// INITIALIZE
// ==========================================
initCookieConsent();
});