backup and fixes
This commit is contained in:
423
Profice WebSite backup/scripts/cookie-consent.js
Normal file
423
Profice WebSite backup/scripts/cookie-consent.js
Normal file
@@ -0,0 +1,423 @@
|
||||
/**
|
||||
* 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();
|
||||
});
|
||||
Reference in New Issue
Block a user