1/** 2 * GDPR Cookie Consent 3 * A script to handle GDPR compliant cookie consent 4 */ 5 6(function ($) { 7 // Cookie consent configuration 8 const cookieConsent = { 9 storageKey: "pp_cookie_consent", 10 consentCategories: { 11 necessary: { 12 name: "Strictly Necessary", 13 description: 14 "These cookies are essential for the website to function properly and cannot be disabled.", 15 required: true, 16 defaultEnabled: true, 17 cookies: [ 18 { 19 name: "G_ENABLED_IDPS", 20 description: "Used to Sign in with Google", 21 }, 22 { 23 name: "_dc_gtm_UA-578862-1", 24 description: 25 "Associated with Google Tag Manager to load scripts", 26 }, 27 { 28 name: "li_gc", 29 description: 30 "Used to store consent for non-essential cookies", 31 }, 32 { 33 name: "__cf_bm", 34 description: 35 "Used to distinguish between humans and bots", 36 }, 37 { 38 name: "PHPSESSID", 39 description: "Used to maintain user session variables", 40 }, 41 ], 42 }, 43 performance: { 44 name: "Performance", 45 description: 46 "These cookies collect information about how visitors use our website, which pages they visited and which links they clicked on.", 47 required: false, 48 defaultEnabled: false, 49 cookies: [ 50 { 51 name: "_ga_LNB0LRZJ9G", 52 description: 53 "Used by Google Analytics to persist session state", 54 }, 55 { 56 name: "_ga", 57 description: 58 "Used to distinguish unique users by Google Analytics", 59 }, 60 { 61 name: "_gid", 62 description: 63 "Stores a unique value for each page visited and tracks pageviews", 64 }, 65 { 66 name: "_ga_T2HSWQHXTR", 67 description: 68 "Used by Google Analytics to persist session state", 69 }, 70 ], 71 }, 72 targeting: { 73 name: "Targeting", 74 description: 75 "These cookies are used to deliver advertisements more relevant to you and your interests.", 76 required: false, 77 defaultEnabled: false, 78 cookies: [ 79 { 80 name: "_gcl_au", 81 description: 82 "Used by Google AdSense for experimenting with advertisement efficiency", 83 }, 84 { 85 name: "_fbp", 86 description: 87 "Used by Meta to deliver advertisement products", 88 }, 89 { 90 name: "bcookie", 91 description: 92 "Microsoft MSN cookie for sharing content via social media", 93 }, 94 { 95 name: "muc_ads", 96 description: 97 "Used for targeting and advertising purposes", 98 }, 99 { 100 name: "lidc", 101 description: 102 "Microsoft MSN cookie that ensures proper functioning of the website", 103 }, 104 { 105 name: "personalization_id", 106 description: 107 "Carries information about how the user uses the website and advertising", 108 }, 109 ], 110 }, 111 }, 112 }; 113 114 // Helper function to set cookie 115 function setCookie(name, value, days) { 116 let expires = ""; 117 if (days) { 118 const date = new Date(); 119 date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000); 120 expires = "; expires=" + date.toUTCString(); 121 } 122 document.cookie = 123 name + "=" + (value || "") + expires + "; path=/; SameSite=Lax"; 124 } 125 126 // Helper function to get cookie 127 function getCookie(name) { 128 const nameEQ = name + "="; 129 const ca = document.cookie.split(";"); 130 for (let i = 0; i < ca.length; i++) { 131 let c = ca[i]; 132 while (c.charAt(0) === " ") c = c.substring(1, c.length); 133 if (c.indexOf(nameEQ) === 0) 134 return c.substring(nameEQ.length, c.length); 135 } 136 return null; 137 } 138 139 // Helper function to delete cookie 140 function deleteCookie(name) { 141 document.cookie = 142 name + "=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;"; 143 } 144 145 // Get saved consent from localStorage 146 function getSavedConsent() { 147 const consentData = localStorage.getItem(cookieConsent.storageKey); 148 if (consentData) { 149 try { 150 return JSON.parse(consentData); 151 } catch (e) { 152 console.error("Error parsing saved consent data", e); 153 } 154 } 155 return null; 156 } 157 158 // Save consent to localStorage 159 function saveConsent(consentData) { 160 localStorage.setItem( 161 cookieConsent.storageKey, 162 JSON.stringify(consentData) 163 ); 164 165 // Set a cookie to indicate consent is given
166 setCookie("cookie_notice", "true", 365); 167 } 168 169 // Create HTML for the cookie consent modal 170 function createConsentModalHTML() { 171 let cookieCategoriesHTML = ""; 172 173 // Generate HTML for each category 174 for (const category in cookieConsent.consentCategories) { 175 const categoryData = cookieConsent.consentCategories[category]; 176 const isDisabled = categoryData.required; 177 const isChecked = categoryData.defaultEnabled; 178 179 let cookiesHTML = ""; 180 categoryData.cookies.forEach((cookie) => { 181 cookiesHTML += ` 182 <div class="cookie-detail"> 183 <div class="cookie-name">${cookie.name}</div> 184 <div class="cookie-description">${cookie.description}</div> 185 </div>`; 186 }); 187 188 cookieCategoriesHTML += ` 189 <div class="cookie-category" data-category="${category}"> 190 <div class="cookie-category-header"> 191 <label class="cookie-consent-switch"> 192 <input type="checkbox" data-category="${category}" ${ 193 isChecked ? "checked" : "" 194 } ${isDisabled ? "disabled" : ""}> 195 <span class="cookie-consent-slider"></span> 196 </label> 197 <div class="cookie-category-name">${categoryData.name}</div> 198 ${ 199 categoryData.required 200 ? '<div class="cookie-category-required">Required</div>' 201 : "" 202 } 203 </div> 204 <div class="cookie-category-details"> 205 <p>${categoryData.description}</p> 206 ${cookiesHTML} 207 </div> 208 </div>`; 209 } 210 211 // Build complete modal HTML 212 const modalHTML = ` 213 <div class="cookie-consent-modal"> 214 <div class="cookie-consent-container"> 215 <div class="cookie-consent-header"> 216 <div> 217 <h2 class="cookie-consent-title">Cookie Settings</h2> 218 <p class="cookie-consent-description"> 219 We use cookies to enhance your browsing experience, analyze site traffic, and personalize content. 220 Below you can choose which cookies you want to allow on this site. 221 Please note that restricting some cookies may impact the functionality of the website. 222 </p> 223 </div> 224 </div> 225 <div class="cookie-consent-body"> 226 <div class="cookie-consent-options"> 227 <div class="cookie-categories"> 228 ${cookieCategoriesHTML} 229 </div> 230 </div> 231 </div> 232 <div class="cookie-consent-actions"> 233 <button class="cookie-consent-btn cookie-consent-btn-secondary" id="cookie-reject-all">Reject All</button> 234 <button class="cookie-consent-btn cookie-consent-btn-tertiary" id="cookie-accept-necessary">Accept Necessary</button> 235 <button class="cookie-consent-btn cookie-consent-btn-primary" id="cookie-accept-all">Accept All</button> 236 <button class="cookie-consent-btn cookie-consent-btn-tertiary" id="cookie-save-preferences">Save Preferences</button> 237 </div> 238 </div> 239 </div> 240 `; 241 242 return modalHTML; 243 } 244 245 // Apply user consent 246 function applyConsent(consentData) { 247 // Handle cookies based on consent 248 if (!consentData.performance) { 249 // Remove performance cookies 250 deleteCookie("_ga_LNB0LRZJ9G"); 251 deleteCookie("_ga"); 252 deleteCookie("_gid"); 253 deleteCookie("_ga_T2HSWQHXTR"); 254 } 255 256 if (!consentData.targeting) { 257 // Remove targeting cookies 258 deleteCookie("_gcl_au"); 259 deleteCookie("_fbp");
260 deleteCookie("bcookie"); 261 deleteCookie("muc_ads"); 262 deleteCookie("lidc"); 263 deleteCookie("personalization_id"); 264 } 265 266 // Handle Google Analytics based on consent 267 if (typeof window.ga !== "undefined") { 268 if (!consentData.performance) { 269 window["ga-disable-UA-578862-1"] = true; 270 } else { 271 window["ga-disable-UA-578862-1"] = false; 272 } 273 } 274 } 275 276 // Get current consent settings from form 277 function getCurrentConsentFromForm() { 278 const consent = { 279 necessary: true, // Always required 280 performance: $( 281 '.cookie-consent-modal input[data-category="performance"]' 282 ).is(":checked"), 283 targeting: $( 284 '.cookie-consent-modal input[data-category="targeting"]' 285 ).is(":checked"), 286 timestamp: new Date().toISOString(), 287 }; 288 return consent; 289 } 290 291 // Initialize cookie consent 292 function initCookieConsent() { 293 // Create and append modal to body 294 $("body").append(createConsentModalHTML()); 295 296 const $modal = $(".cookie-consent-modal");
297 const $toggleButton = $(".cookie-settings-toggle"); 298 const savedConsent = getSavedConsent(); 299 300 // If no consent saved, show modal 301 if (!savedConsent) { 302 $modal.show(); 303 } else { 304 // Apply saved consent 305 applyConsent(savedConsent); 306 307 // Update form to match saved consent 308 for (const category in savedConsent) { 309 if (category !== "timestamp") { 310 $(`input[data-category="${category}"]`).prop( 311 "checked", 312 savedConsent[category] 313 ); 314 } 315 } 316 } 317 318 // Event handler for category expansion 319 $(".cookie-category").on("click", function (e) { 320 if ( 321 !$(e.target).is("input") && 322 !$(e.target).hasClass("cookie-consent-slider") 323 ) { 324 $(this).toggleClass("expanded"); 325 } 326 }); 327 328 // Accept all cookies 329 $("#cookie-accept-all").on("click", function () { 330 const consent = { 331 necessary: true, 332 performance: true, 333 targeting: true, 334 timestamp: new Date().toISOString(), 335 }; 336 337 saveConsent(consent); 338 applyConsent(consent); 339 $modal.hide(); 340 }); 341 342 // Reject all cookies except necessary 343 $("#cookie-reject-all").on("click", function () { 344 const consent = { 345 necessary: true, 346 performance: false, 347 targeting: false, 348 timestamp: new Date().toISOString(), 349 }; 350 351 saveConsent(consent); 352 applyConsent(consent); 353 $modal.hide(); 354 }); 355 356 // Accept only necessary cookies 357 $("#cookie-accept-necessary").on("click", function () { 358 const consent = { 359 necessary: true, 360 performance: false, 361 targeting: false, 362 timestamp: new Date().toISOString(), 363 }; 364 365 saveConsent(consent); 366 applyConsent(consent); 367 $modal.hide(); 368 }); 369 370 // Save custom preferences 371 $("#cookie-save-preferences").on("click", function () { 372 const consent = getCurrentConsentFromForm(); 373 374 saveConsent(consent); 375 applyConsent(consent); 376 $modal.hide(); 377 }); 378 379 // Toggle settings button 380 $toggleButton.on("click", function () { 381 $modal.show(); 382 }); 383 } 384 385 // Initialize when DOM is ready 386 $(document).ready(function () { 387 // Initialize cookie consent 388 initCookieConsent(); 389 390 // Remove old cookie bar if it exists 391 $("#cookie_bar").remove(); 392 }); 393})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.