1// Copyright © Springbok. Sligro is granted a perpetual, irrevocable and royalty-free 2// right to use, host, maintain and modify this First Party Pixel for its business 3// purposes, including after termination of Springbokâs services. Third-party service 4// providers acting on behalf of Sligro may access and manage the code solely to provide 5// services to Sligro. Any other use, reproduction, distribution, reuse or commercial 6// exploitation of this code or derivative works is strictly prohibited. 7 8window.pixel = { 9 // Configuration object 10 configuration: { 11 init_unix_timestamp: Date.now(), 12 last_interaction_unix_timestamp_ms: Date.now(), 13 cookie_value_separator: "--", 14 user_cookie_name: "sfguid", 15 cookie_expiration_milliseconds: 31536000000, // 365 days 16 session_cookie_name: "sfgsid", 17 session_cookie_lifetime_milliseconds: Number(1800000), // 30 min 18 cookie_domain: window.location.hostname.split(/\./).slice(-2).join("."), 19 session_start_trigger: false, 20 session_start_reasons: [], 21 session_start_sent: false, 22 session_start_sent_storage_name: "sfg_session_start_sent", 23 event_id_name: "sfgeid", 24 browser_support_safe_uuid: true, 25 consent_cookie_name: "sfg_consent", 26 cmp_update_handled: false, 27 session_start_handled: false, 28 floodgate_name: "sfg_floodgate_events", 29 floodgate_open: false, 30 session_info_storage_name: "sfg_session_info", 31 // click_ids_cookie_name: configuration.click_ids_cookie_name, 32 // microsoft_ads_tag_id: configuration.microsoft_ads_tag_id, 33 allow_pings: false, 34 blocking_detected: false, 35 }, 36 37 // The user manager object 38 user_manager: { 39 is_legacy_user_cookie_format: function (cookie_value) { 40 // Legacy format: U + random digits + "-" + unix timestamp 41 return /^U\d+-\d+$/.test(cookie_value || ""); 42 }, 43 44 get_legacy_user_cookie_expiration_ms: function (cookie_value) { 45 // Legacy value format: U<random>-<unix_seconds_created> 46 var created_timestamp_seconds = window.pixel.helpers.safe_parse_int((cookie_value || "").split("-")[1]); 47 if (!created_timestamp_seconds) { 48 return 0; 49 } 50 return (created_timestamp_seconds * 1000) + window.pixel.configuration.cookie_expiration_milliseconds; 51 }, 52 53 // A function the check if the user cookie is set. 54 user_cookie_exists: function() { 55 var configuration = window.pixel.configuration; 56 return window.pixel.helpers.get_cookie_value(configuration.user_cookie_name) !== null; 57 }, 58 59 // A function to check if the user cookie is expired. 60 is_user_cookie_expired: function() { 61 var configuration = window.pixel.configuration; 62 63 if (!window.pixel.user_manager.user_cookie_exists()) { 64 return true; 65 } 66 67 var user_input = window.pixel.helpers.get_cookie_value(configuration.user_cookie_name); 68 if (window.pixel.user_manager.is_legacy_user_cookie_format(user_input)) { 69 var legacy_expiration_ms = window.pixel.user_manager.get_legacy_user_cookie_expiration_ms(user_input); 70 return legacy_expiration_ms === 0 || legacy_expiration_ms < Date.now(); 71 } 72 var user_expire = parseInt(user_input.split(configuration.cookie_value_separator)[1]); 73 return new Date(user_expire) < new Date(); 74 }, 75 76 // A function to set the user cookie. 77 create_user_cookie: function() { 78 var configuration = window.pixel.configuration; 79 var current_user_cookie_value = window.pixel.helpers.get_cookie_value(configuration.user_cookie_name); 80 81 // Preserve existing legacy payload exactly as-is. 82 if (window.pixel.user_manager.is_legacy_user_cookie_format(current_user_cookie_value)) { 83 window.pixel.helpers.set_cookie( 84 configuration.user_cookie_name, 85 current_user_cookie_value, 86 configuration.cookie_expiration_milliseconds, 87 '/', 88 configuration.cookie_domain 89 ); 90 return current_user_cookie_value; 91 } 92 93 var user_id = window.pixel.helpers.generate_uuid(); 94 var cookie_lifetime_milliseconds = configuration.cookie_expiration_milliseconds; 95 var user_expire = new Date().setTime(new Date().getTime() + cookie_lifetime_milliseconds).toString(); 96 var user_cookie_value = user_id + configuration.cookie_value_separator + user_expire; 97 98 window.pixel.helpers.set_cookie(configuration.user_cookie_name, user_cookie_value, cookie_lifetime_milliseconds, '/', configuration.cookie_domain); 99 return user_id; 100 }, 101 102 // Extend the lifetime of the user cookie. 103 extend_user_cookie_lifetime: function() { 104 var configuration = window.pixel.configuration; 105 var current_user_cookie_value = window.pixel.helpers.get_cookie_value(configuration.user_cookie_name); 106 107 if (window.pixel.user_manager.is_legacy_user_cookie_format(current_user_cookie_value)) { 108 // Preserve legacy cookie payload exactly as-is. 109 window.pixel.helpers.set_cookie( 110 configuration.user_cookie_name, 111 current_user_cookie_value, 112 configuration.cookie_expiration_milliseconds, 113 '/', 114 configuration.cookie_domain 115 ); 116 return current_user_cookie_value; 117 } 118 119 var user_id = window.pixel.user_manager.get_user_cookie_values()[0]; 120 121 var user_expire = new Date().setTime(new Date().getTime() + configuration.cookie_expiration_milliseconds).toString(); 122 var user_cookie_value = user_id + configuration.cookie_value_separator + user_expire; 123 window.pixel.helpers.set_cookie(configuration.user_cookie_name, user_cookie_value, configuration.cookie_expiration_milliseconds, '/', configuration.cookie_domain); 124 125 return user_id; 126 }, 127 128 get_user_cookie_values: function () { 129 // Return in this order: user id, user expiration time 130 var configuration = window.pixel.configuration; 131 var user_cookie_value = window.pixel.helpers.get_cookie_value(configuration.user_cookie_name); 132 if (user_cookie_value !== null) { 133 if (window.pixel.user_manager.is_legacy_user_cookie_format(user_cookie_value)) { 134 return [user_cookie_value, undefined]; 135 } 136 var user_cookie_value_parts = user_cookie_value.split("--"); 137 return user_cookie_value_parts; 138 } 139 return [undefined, undefined]; 140 }, 141 }, 142 143 // The session manager object 144 session_manager: { 145 session_cookie_exists: function () { 146 var configuration = window.pixel.configuration; 147 148 return (window.pixel.helpers.get_cookie_value(configuration.session_cookie_name) !== null); 149 }, 150 151 is_session_cookie_expired: function () { 152 var configuration = window.pixel.configuration; 153 154 if (!window.pixel.session_manager.session_cookie_exists()) { 155 return true; 156 } 157 158 var session_cookie_value = window.pixel.helpers.get_cookie_value( 159 configuration.session_cookie_name 160 ); 161 var session_expiration = parseInt(session_cookie_value.split("--")[1]); 162 return new Date(session_expiration) < new Date(); 163 }, 164 165 get_session_cookie_values: function () { 166 var configuration = window.pixel.configuration 167 // Return in this order: session id, session expiration time, session start time, session number 168 var session_cookie_value = window.pixel.helpers.get_cookie_value(configuration.session_cookie_name); 169 if (session_cookie_value !== null) { 170 var session_cookie_value_parts = session_cookie_value.split(configuration.cookie_value_separator); 171 return session_cookie_value_parts; 172 } 173 return [undefined, undefined, undefined, undefined]; 174 }, 175 176 create_session_cookie: function () { 177 window.pixel.helpers.log_debug("Session cookie creation started:", "log"); 178 var configuration = window.pixel.configuration; 179 var session_start_timestamp_seconds = Math.floor(Date.now() / 1000); 180 181 // Default value 182 // var session_number = 1; 183 // // If session number exists in the user cookie 184 // var user_cookie_values = window.pixel.user_manager.get_user_cookie_values(); 185 // // If only user exists, get it from the user and increment it with 1 (since this function is started to launch a new session) 186 // if (user_cookie_values[1] !== undefined) { 187 // session_number = window.pixel.helpers.safe_parse_int(user_cookie_values[1]) + 1; 188 // } 189 var session_id = window.pixel.helpers.generate_uuid(); 190 var session_expiration = new Date().getTime() + configuration.session_cookie_lifetime_milliseconds; 191 var session_cookie_new_value = session_id + configuration.cookie_value_separator + session_expiration + configuration.cookie_value_separator + session_start_timestamp_seconds; 192 193 // Set the session cookie with the session start time 194 //{session id}--{session expiration}--{session start time} 195 window.pixel.helpers.set_cookie(configuration.session_cookie_name, session_cookie_new_value, configuration.session_cookie_lifetime_milliseconds, "/", window.pixel.helpers.get_cookie_domain(window.location.hostname)); 196 197 // Update the user cookie with the session number variable 198 //{user id}--{session number} 199 // var user_cookie_new_value = user_cookie_values[0] + "--" + session_number; 200 // window.pixel.helpers.set_cookie(configuration.user_cookie_name, user_cookie_new_value, configuration.cookie_expiration_milliseconds, "/", window.pixel.helpers.get_cookie_domain(window.location.hostname)); 201 return session_id; 202 }, 203 204 extend_session_cookie_lifetime: function () { 205 var configuration = window.pixel.configuration; 206 207 if (!window.pixel.session_manager.session_cookie_exists()) { 208 return undefined; 209 } 210 211 if (window.pixel.session_manager.is_session_cookie_expired()) { 212 return window.pixel.session_manager.create_session_cookie(); 213 } 214 215 var session_cookie_values = window.pixel.session_manager.get_session_cookie_values(); 216 var new_session_expiration = new Date().getTime() + 217 configuration.session_cookie_lifetime_milliseconds; 218 var updated_session_cookie_value = session_cookie_values[0] + 219 configuration.cookie_value_separator + 220 new_session_expiration + 221 configuration.cookie_value_separator + 222 session_cookie_values[2]; 223 window.pixel.helpers.set_cookie( 224 configuration.session_cookie_name, 225 updated_session_cookie_value, 226 configuration.session_cookie_lifetime_milliseconds, 227 "/", 228 window.pixel.helpers.get_cookie_domain(window.location.hostname) 229 ); 230 231 return session_cookie_values[0]; 232 }, 233 }, 234 235 // Helper functions 236 helpers: { 237 generate_uuid_non_secure: function () { 238 window.pixel.configuration.browser_support_safe_uuid = false;
239 return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace( 240 /[018]/g, 241 function (c) { 242 return ( 243 c ^ 244 (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4))) 245 ).toString(16); 246 } 247 ); 248 }, 249 generate_uuid_secure: function () { 250 window.pixel.configuration.browser_support_safe_uuid = true; 251 return crypto.randomUUID(); 252 }, 253 generate_uuid: function () { 254 try { 255 if (typeof crypto.randomUUID === "function") { 256 return window.pixel.helpers.generate_uuid_secure(); 257 } else if (typeof crypto.getRandomValues === "function") { 258 return window.pixel.helpers.generate_uuid_non_secure(); 259 } 260 } catch (e) { 261 window.pixel.configuration.browser_support_safe_uuid = false; 262 return ( 263 Math.floor(100000000 + Math.random() * 900000000).toString() + 264 "." + 265 new Date().getTime().toString() 266 ); 267 } 268 269 return ( 270 Math.floor(100000000 + Math.random() * 900000000).toString() + 271 "." + 272 new Date().getTime().toString() 273 ); 274 }, 275 get_cookie_value: function (cookie_name) { 276 var value = "; " + document.cookie; 277 var parts = value.split("; " + cookie_name + "="); 278 279 if (parts.length == 2) { 280 return parts.pop().split(";").shift(); 281 } 282 283 return null; 284 }, 285 set_cookie: function (cookie_name, cookie_value, cookie_lifetime_in_milliseconds, cookie_path, cookie_domain) { 286 var cookie_secure = ";secure"; 287 var cookie_samesite = "lax"; 288 289 var d = new Date(); 290 d.setTime(d.getTime() + cookie_lifetime_in_milliseconds); 291 document.cookie = cookie_name + "=" + cookie_value + ";expires=" + d.toUTCString() + ";path=" + cookie_path + ";domain=" + cookie_domain + cookie_secure + ";SameSite=" + cookie_samesite; 292 }, 293 get_cookie_domain: function (hostname) { 294 var publicSuffixes = ['co.uk', 'com.au', 'org.uk']; 295 var parts = hostname.split('.'); 296 297 for (let i = 0; i < publicSuffixes.length; i++) { 298 var suffix = publicSuffixes[i]; 299 if (hostname.endsWith(suffix)) { 300 var suffixParts = suffix.split('.').length; 301 return '.' + parts.slice(-suffixParts - 1).join('.'); 302 } 303 } 304 return '.' + parts.slice(-2).join('.'); 305 }, 306 get_url_parameter_value: function (url_parameter_name) { 307 var urlParams = new URLSearchParams(window.location.search); 308 return urlParams.get(url_parameter_name) || null; 309 }, 310 log_debug: function (message, type) { 311 type = type || "log"; // Default parameter handling for ES5 compatibility 312 313 switch (type) { 314 case "log": 315 console.log(message); 316 break; 317 case "warn": 318 console.warn(message); 319 break; 320 case "error": 321 console.error(message); 322 break; 323 default: 324 console.log(message); 325 } 326 }, 327 hash: async function (input) { 328 if (!input) { 329 return ""; 330 } 331 try { 332 return Array.from( 333 new Uint8Array( 334 await crypto.subtle.digest( 335 "SHA-256", 336 new TextEncoder().encode(input.trim().toLowerCase()) 337 ) 338 ) 339 ) 340 .map((b) => b.toString(16).padStart(2, "0")) 341 .join(""); 342 } catch (error) { 343 return input; 344 } 345 }, 346 safe_parse_float: function (value) { 347 try { 348 if (value === null || typeof value === "undefined") { 349 return 0; 350 } 351 var parsed = parseFloat(value); 352 if (isNaN(parsed)) { 353 return 0; 354 } 355 return parsed; 356 } catch (e) { 357 return 0; 358 } 359 }, 360 safe_parse_int: function (value) { 361 try { 362 if (value === null || typeof value === "undefined") { 363 return 0; 364 } 365 var parsed = parseInt(value); 366 if (isNaN(parsed)) { 367 return 0; 368 } 369 return parsed; 370 } catch (e) { 371 return 0; 372 } 373 }, 374 safe_parse_string: function (value) { 375 if (value === null || typeof value === "undefined") { 376 return ""; 377 } 378 return String(value); 379 }, 380 }, 381 382 // All consent management functionality 383 consent_manager: { 384 timeout_consent_listener_updates: function () { 385 // Reset flag after 1.5 seconds 386 setTimeout(function () { 387 window.pixel.configuration.cmp_update_handled = false;
388 }, 1500); 389 }, 390 391 retrieve_consent_state: function () { 392 var onetrust_cookie = window.pixel.helpers.get_cookie_value("OptanonConsent"); 393 if (onetrust_cookie !== null) { 394 var decoded_onetrust = decodeURIComponent(onetrust_cookie); 395 var groupsMatch = decoded_onetrust.match(/groups=([^;&]+)/); 396 var allow_strictly_necessary = "0", allow_analytical = "0", allow_functional = "0", allow_advertising = "0", allow_social_media = "0", allow_personalization = "0"; 397 if (groupsMatch) { 398 var groups = groupsMatch[1].split(','); 399 groups.forEach(function (group) { 400 var parts = group.split(':'); 401 if (parts[0] === "C0001") { 402 allow_strictly_necessary = parts[1] === "1" ? "1" : "0"; 403 } 404 if (parts[0] === "C0002") { 405 allow_analytical = parts[1] === "1" ? "1" : "0"; 406 } 407 if (parts[0] === "C0003") { 408 allow_functional = parts[1] === "1" ? "1" : "0"; 409 } 410 if (parts[0] === "C0004") { 411 allow_advertising = parts[1] === "1" ? "1" : "0"; 412 } 413 if (parts[0] === "C0005") { 414 allow_social_media = parts[1] === "1" ? "1" : "0"; 415 } 416 if (parts[0] === "C0007") { 417 allow_personalization = parts[1] === "1" ? "1" : "0"; 418 } 419 }); 420 } 421 return { 422 ad_storage: allow_advertising, 423 analytics_storage: allow_analytical, 424 functionality_storage: allow_strictly_necessary, 425 personalization_storage: allow_personalization, 426 security_storage: allow_strictly_necessary, 427 ad_user_data: allow_advertising, 428 ad_personalization: allow_personalization, 429 social_media_storage: allow_social_media 430 } 431 } 432 }, 433 434 435 436 437 // Initial consent check sequence 438 initial_consent_enforcement: function () { 439 // Start initial consent enforcement 440 window.pixel.helpers.log_debug("Initial consent enforcement triggered!", "log"); 441 442 // First check the initial pixel consent cookie value (if available) 443 var pixel_consent_cookie = window.pixel.helpers.get_cookie_value(window.pixel.configuration.consent_cookie_name); 444 445 // Set initial check variables related to consent and system detection 446 var initial_pixel_allow_marketing = false; // pixel itself assumes marketing is not allowed by default 447 window.pixel.configuration.cmp_allow_marketing = false; // pixel assumes marketing is not allowed by default by the CMP 448 window.pixel.configuration.blocking_detected = undefined; // No blocking detected by default 449 window.pixel.helpers.log_debug("Initial consent enforcement cookie value: " + (pixel_consent_cookie || "null"), "log"); 450 451 // If the pixel consent cookie is NOT emtpy 452 if (pixel_consent_cookie !== null) { 453 window.pixel.helpers.log_debug("Consent cookie !== to null, so open floodgate.", "log"); 454 window.pixel.configuration.floodgate_open = true; 455 try { 456 // If the value of the initial pixel consent cookie is 1, then this indicates that here is no dynamic loading necessary 457 initial_pixel_allow_marketing = JSON.parse(decodeURIComponent(pixel_consent_cookie)).allow_marketing === "1"; 458 // If the blocking parameter is detected with a high probability (1), change the check variable to 1 else to 0 (because detection is completed) 459 if (JSON.parse(decodeURIComponent(pixel_consent_cookie)).b === "1") { 460 window.pixel.configuration.blocking_detected = "1"; 461 } else if (JSON.parse(decodeURIComponent(pixel_consent_cookie)).b === "0") { 462 window.pixel.configuration.blocking_detected = "0"; 463 } 464 } catch (parse_error) { 465 window.pixel.helpers.log_debug("pixel consent cookie parse error:", "log"); 466 window.pixel.helpers.log_debug(parse_error, "log"); 467 } 468 } 469 470 /// CMP logic here 471 if (typeof window.pixel.consent_manager.cmp_init === "function") { 472 window.pixel.helpers.log_debug("start cmp init.", "log");
473 window.pixel.consent_manager.cmp_init(); 474 } 475 476 // Evaluate floodgate after to trigger the pixel events 477 if (window.pixel.configuration.floodgate_open === true && window.pixel.configuration.cmp_update_handled === true) { 478 window.pixel.helpers.log_debug("Floodgate evaluation triggered from initial consent enforcement.", "log"); 479 window.pixel.consent_manager.evaluate_consent_floodgate(); 480 } 481 482 return window.pixel.configuration.cmp_allow_marketing; 483 }, 484 // Function to evaluate the floodgate status 485 evaluate_consent_floodgate: function () { 486 window.pixel.helpers.log_debug("Start Floodgate evaluation...", "log"); 487 // First check if the floodgate is open 488 if (!window.pixel.configuration.floodgate_open) { 489 window.pixel.helpers.log_debug( 490 "Floodgate evaluation stopped. Floodgate closed", 491 "log" 492 ); 493 return; 494 } 495 496 // Retrieve floodgate events 497 var floodgate_events = []; 498 if ( typeof sessionStorage !== "undefined" && typeof window.pixel.floodgate_events === "undefined" ) { 499 floodgate_events = JSON.parse(sessionStorage.getItem(window.pixel.configuration.floodgate_name)) || []; 500 } else if (typeof window.pixel.floodgate_events !== "undefined") { 501 floodgate_events = window.pixel.floodgate_events; 502 } 503 window.pixel.helpers.log_debug( 504 "Collected floodgated events: " + floodgate_events.length.toString(), 505 "log" 506 ); 507 508 // Store session info if available 509 if (typeof window.pixel.session_info !== "undefined" && typeof sessionStorage !== "undefined") { 510 sessionStorage.setItem(window.pixel.configuration.session_info_storage_name, window.pixel.session_info); 511 } 512 513 // If no floodgate events exist, log and exit 514 if (floodgate_events.length === 0) { 515 window.pixel.helpers.log_debug("No Floodgate events sent", "log"); 516 return; 517 } 518 519 // Function to send floodgated events 520 function send_floodgated_events() { 521 window.pixel.helpers.log_debug("Sending floodgated events", "log"); 522 523 for (var i = 0; i < floodgate_events.length; i++) { 524 window.pixel.send_floodgated_event(floodgate_events[i]); 525 } 526 527 // Empty the floodgate to prevent double triggers 528 sessionStorage.removeItem(window.pixel.configuration.floodgate_name); 529 window.pixel.floodgate_events = []; 530 } 531 532 window.pixel.helpers.log_debug( 533 "Evaluation finished with floodgate status: " + 534 window.pixel.configuration.floodgate_open.toString(), 535 "log" 536 ); 537 538 if (!window.pixel.user_manager.user_cookie_exists()) { 539 window.pixel.user_manager.create_user_cookie(); 540 } else if (window.pixel.user_manager.is_user_cookie_expired()) { 541 window.pixel.user_manager.create_user_cookie(); 542 } else { 543 window.pixel.user_manager.extend_user_cookie_lifetime(); 544 } 545 546 if (!window.pixel.session_manager.session_cookie_exists()) { 547 window.pixel.session_manager.create_session_cookie(); 548 } else if (window.pixel.session_manager.is_session_cookie_expired()) { 549 window.pixel.session_manager.create_session_cookie(); 550 } else { 551 window.pixel.session_manager.extend_session_cookie_lifetime(); 552 } 553 554 send_floodgated_events(); 555 }, 556 557 // Function to manually overwrite the consent settings when no CMP is selected 558 update_consent: function (consent_object) { 559 var configuration = window.pixel.configuration; 560 var pixel_consent_cookie = window.pixel.helpers.get_cookie_value(configuration.consent_cookie_name); 561 if (pixel_consent_cookie !== null) { 562 var current_consent_object = JSON.parse(decodeURIComponent(pixel_consent_cookie)); 563 configuration.blocking_detected = "0"; // No blocking detected by default 564 if (JSON.parse(decodeURIComponent(pixel_consent_cookie)).b === "1") { 565 configuration.blocking_detected = "1"; 566 } 567 var updated_consent_object = consent_object; 568 // Add the blocking parameter 569 updated_consent_object.b = configuration.blocking_detected; 570 // Merge new consent values into the current consent object (the current is the one that needs updating) 571 for (var key in updated_consent_object) { 572 if (updated_consent_object.hasOwnProperty(key) && current_consent_object.hasOwnProperty(key)) { 573 current_consent_object[key] = updated_consent_object[key].toString(); 574 } 575 } 576 current_consent_object["unix"] = Date.now(); 577 578 window.pixel.helpers.set_cookie(configuration.consent_cookie_name, encodeURIComponent(JSON.stringify(current_consent_object)), configuration.cookie_expiration_milliseconds, "/", window.pixel.helpers.get_cookie_domain(window.location.hostname) 579 ); 580 } 581 }, 582 583 has_explicit_cmp_consent: function(){ 584 var has_explicit_consent = false;
585 has_explicit_consent = window.pixel.helpers.get_cookie_value("OptanonConsent") !== null; 586 return has_explicit_consent; 587 } 588 }, 589 590 // Send floodgated events 591 send_floodgated_event: function (stored_event) { 592 var configuration = window.pixel.configuration; 593 594 // Determine the default event endpoint based on hostname 595 if (window.location.hostname.includes("acc") || window.location.hostname.includes("tst") || window.location.hostname.includes("test") || window.location.hostname.includes("sligro-digital") || window.location.hostname.includes("localhost")) { 596 configuration.default_event_endpoint = "https://slgcp-test.sligro-digital.nl/functions/pixel/pixel-retrieve"; 597 } else { 598 configuration.default_event_endpoint = "https://slgcp.sligro-digital.nl/functions/pixel/pixel-retrieve"; 599 } 600 601 window.pixel.helpers.log_debug("Preparing floodgated event for sending...", "log"); 602 var current_stored_event = stored_event; 603 var consent_cookie_value = window.pixel.helpers.get_cookie_value( 604 window.pixel.configuration.consent_cookie_name 605 ); 606 var pixel_consent_cookie_value = {}; 607 if (consent_cookie_value) { 608 try { 609 pixel_consent_cookie_value = JSON.parse(decodeURIComponent(consent_cookie_value)); 610 } catch (e) { 611 window.pixel.helpers.log_debug("Error parsing consent cookie: " + e.message, "error"); 612 // handle parse error 613 } 614 } 615 var allow_uid = pixel_consent_cookie_value.allow_uid === "1"; 616 var allow_sid = pixel_consent_cookie_value.allow_sid === "1"; 617 618 // Apply consent settings on floodgated events 619 if (allow_uid) { 620 if (window.pixel.helpers.get_cookie_value(configuration.user_cookie_name) == null) { 621 window.pixel.user_manager.create_user_cookie(); 622 } 623 current_stored_event[configuration.user_cookie_name] = window.pixel.user_manager.get_user_cookie_values()[0]; 624 } else { 625 delete current_stored_event[configuration.user_cookie_name]; 626 } 627 if (allow_sid) { 628 if (window.pixel.helpers.get_cookie_value(configuration.session_cookie_name) == null) { 629 window.pixel.session_manager.create_session_cookie(); 630 } 631 current_stored_event[configuration.session_cookie_name] = window.pixel.session_manager.get_session_cookie_values()[0]; 632 } else { 633 delete current_stored_event[configuration.session_cookie_name]; 634 } 635 // Overwrite the consent object with the recent change 636 current_stored_event.consent = pixel_consent_cookie_value; 637 638 // Add additional floodgate context which we don't want stored before consent. 639 current_stored_event["screen_height"] = screen.height || ""; 640 current_stored_event["screen_width"] = screen.width || ""; 641 current_stored_event["user_agent"] = navigator.userAgent || ""; 642 current_stored_event["language"] = navigator.language || ""; 643 current_stored_event["consent"] = pixel_consent_cookie_value; 644 current_stored_event["consent_state"] = window.pixel.consent_manager.retrieve_consent_state() || undefined; 645 current_stored_event["context"]["floodgated"] = true; 646 current_stored_event["context"]["floodgate_release_unix_timestamp"] = Date.now(); 647 // current_stored_event["context"]["session_number"] = window.pixel.user_manager.get_user_cookie_values()[1]; 648 current_stored_event["context"]["session_start_time"] = window.pixel.session_manager.get_session_cookie_values()[2]; 649 current_stored_event["context"]["engaged_time_ms"] = current_stored_event["event_unix_timestamp"] - configuration.last_interaction_unix_timestamp_ms; 650 configuration.last_interaction_unix_timestamp_ms = current_stored_event["event_unix_timestamp"]; 651 652 // Prepare for data sending to API 653 window.pixel.helpers.log_debug("Sending event data to API...", "log"); 654 if (navigator.sendBeacon) { 655 navigator.sendBeacon(configuration.default_event_endpoint, JSON.stringify(stored_event)); 656 window.pixel.helpers.log_debug("Event sent using sendBeacon", "log"); 657 } else { 658 var xmlhttp = new XMLHttpRequest(); 659 xmlhttp.open("POST", configuration.default_event_endpoint, true); 660 xmlhttp.setRequestHeader("Content-Type", "application/json"); 661 xmlhttp.send(JSON.stringify(stored_event)); 662 window.pixel.helpers.log_debug("Event sent using XMLHttpRequest", "log"); 663 } 664 }, 665 666 // Send event function 667 send_event: function(event_name, context, user, ecommerce, target_params){ 668 var configuration = window.pixel.configuration; 669 670 //get core objects 671 var sfg_core_user = user || {}; 672 var sfg_core_context = context || {}; 673 var sfg_core_ecommerce = ecommerce || {}; 674 var sfg_core_target = target_params || {}; 675 var _ga = window.pixel.helpers.get_cookie_value("_ga") || undefined; 676 677 //add conditional user params 678 sfg_core_user["fbclid"] = window.pixel.helpers.get_cookie_value("sfgfbclid") || undefined; 679 sfg_core_user["msclkid"] = window.pixel.helpers.get_cookie_value("sfgmsclkid") || undefined; 680 sfg_core_user["fbp"] = window.pixel.helpers.get_cookie_value("fbp") || undefined; 681 sfg_core_user["gclid"] = window.pixel.helpers.get_cookie_value("sfggclid") || undefined; 682 sfg_core_user["ehash"] = window.pixel.helpers.get_cookie_value("sfgehash") || undefined; 683 sfg_core_user["hotjar_id"] = window.pixel.helpers.get_cookie_value("_hjSessionUser_") || undefined; // hotjar session_id not working 684 685 for (var i = 0; i < dataLayer.length; i++) { 686 if (dataLayer[i].logged_in !== undefined && dataLayer[i].logged_in !== null && dataLayer[i].logged_in !== "") { 687 sfg_core_user["logged_in"] = dataLayer[i].logged_in; 688 } 689 if (dataLayer[i].customer_guid !== undefined && dataLayer[i].customer_guid !== null && dataLayer[i].customer_guid !== "") { 690 sfg_core_user["customer_guid"] = dataLayer[i].customer_guid; 691 } 692 if (dataLayer[i].customer_id !== undefined && dataLayer[i].customer_id !== null && dataLayer[i].customer_id !== "") { 693 sfg_core_user["customer_id"] = dataLayer[i].customer_id; 694 } 695 if (dataLayer[i].customer_root_id !== undefined && dataLayer[i].customer_root_id !== null && dataLayer[i].customer_root_id !== "") { 696 sfg_core_user["customer_root_id"] = dataLayer[i].customer_root_id; 697 } 698 if (dataLayer[i].customer_segment !== undefined && dataLayer[i].customer_segment !== null && dataLayer[i].customer_segment !== "") { 699 sfg_core_user["customer_segment"] = dataLayer[i].customer_segment; 700 } 701 if (dataLayer[i].user_bs_location !== undefined && dataLayer[i].user_bs_location !== null && dataLayer[i].user_bs_location !== "") { 702 sfg_core_user["user_bs_location"] = dataLayer[i].user_bs_location; 703 } 704 if (dataLayer[i].user_email_hashed !== undefined && dataLayer[i].user_email_hashed !== null && dataLayer[i].user_email_hashed !== "") { 705 sfg_core_user["user_email_hashed"] = dataLayer[i].user_email_hashed; 706 } 707 if (dataLayer[i].user_zb_location !== undefined && dataLayer[i].user_zb_location !== null && dataLayer[i].user_zb_location !== "") { 708 sfg_core_user["user_zb_location"] = dataLayer[i].user_zb_location; 709 } 710 if (dataLayer[i].user_permissions !== undefined && dataLayer[i].user_permissions !== null) { 711 // Check if user_permissions is a string 712 if (typeof dataLayer[i].user_permissions === "string" && dataLayer[i].user_permissions !== "") { 713 sfg_core_user["user_permissions"] = dataLayer[i].user_permissions; 714 } 715 // Check if user_permissions is an array 716 else if (Array.isArray(dataLayer[i].user_permissions) && dataLayer[i].user_permissions.length > 0) { 717 sfg_core_user["user_permissions"] = dataLayer[i].user_permissions.join("|"); 718 } 719 // Check if user_permissions is an object 720 else if (typeof dataLayer[i].user_permissions === "object" && Object.keys(dataLayer[i].user_permissions).length > 0) { 721 sfg_core_user["user_permissions"] = Object.values(dataLayer[i].user_permissions).join("|"); 722 } 723 } 724 } 725 726 // Determine the default event endpoint based on hostname 727 if (window.location.hostname.includes("acc") || window.location.hostname.includes("tst") || window.location.hostname.includes("test") || window.location.hostname.includes("sligro-digital") || window.location.hostname.includes("localhost")) { 728 configuration.default_event_endpoint = "https://slgcp-test.sligro-digital.nl/functions/pixel/pixel-retrieve"; 729 } else { 730 configuration.default_event_endpoint = "https://slgcp.sligro-digital.nl/functions/pixel/pixel-retrieve"; 731 } 732 733 // Construct the event context 734 var event_data = {}; 735 var dlObj = (typeof dataLayer !== 'undefined' && dataLayer.length > 0) ? dataLayer[0] : {};
736 event_data[configuration.event_id_name] = window.pixel.helpers.generate_uuid(); 737 event_data["event"] = event_name; 738 event_data["event_unix_timestamp"] = Date.now(); 739 event_data["timestamp"] = new Date().toISOString(); 740 event_data["ga_cid"] = _ga; 741 event_data["context"] = sfg_core_context || {}; 742 event_data["location"] = { 743 fullurl: document.location.href || undefined, 744 pathname: document.location.pathname || undefined, 745 query: window.location.search || undefined, 746 hash: window.location.hash || undefined, 747 hostname: window.location.hostname || undefined, 748 protocol: window.location.protocol || undefined, 749 referrer: document.referrer || undefined, 750 title: document.title || undefined, 751 environment: dlObj.environment || "unknown", 752 platform: dlObj.platform || "unknown", 753 platform_country_code: (dlObj.platform_country_code || "unknown").toLowerCase() 754 }; 755 event_data["context"]["browser_support_safe_uuid"] = configuration.browser_support_safe_uuid; 756 event_data["context"]["init_unix_timestamp"] = configuration.init_unix_timestamp; 757 // event_data["context"]["session_number"] = window.pixel.user_manager.get_user_cookie_values()[1]; 758 event_data["context"]["session_start_time"] = window.pixel.session_manager.get_session_cookie_values()[2]; 759 event_data["context"]["engaged_time_ms"] = event_data["event_unix_timestamp"] - configuration.last_interaction_unix_timestamp_ms; 760 event_data["user"] = sfg_core_user || {}; 761 event_data["ecommerce"] = sfg_core_ecommerce || {}; 762 event_data["target_params"] = sfg_core_target || {}; 763 764 // Don't reset the engaged time if the event is a non-interaction event 765 if (event_data["context"].hasOwnProperty("non_interaction") && event_data["context"]["non_interaction"] !== "1") { 766 configuration.last_interaction_unix_timestamp_ms = event_data["event_unix_timestamp"]; 767 } 768 769 // If consent cookie is available and floodgate open, handle based on the pixel consent cookie. Otherwise the event will be floodgated later 770 window.pixel.helpers.log_debug("Floodgate open: " + configuration.floodgate_open.toString(), "log"); 771 window.pixel.helpers.log_debug("Consent cookie value: " + window.pixel.helpers.get_cookie_value(decodeURIComponent(configuration.consent_cookie_name)), "log"); 772 window.pixel.helpers.log_debug("User cookie value: " + window.pixel.user_manager.get_user_cookie_values()[0], "log" ); 773 774 // Only push events to the pixel API if the floodgates are open! 775 if (configuration.floodgate_open) { 776 // First check consent information 777 var consent_cookie_value = window.pixel.helpers.get_cookie_value(configuration.consent_cookie_name); 778 var pixel_consent_cookie_value = {}; 779 if (consent_cookie_value) { 780 pixel_consent_cookie_value = JSON.parse(decodeURIComponent(consent_cookie_value)); 781 } 782 var allow_uid = pixel_consent_cookie_value.allow_uid === "1"; 783 var allow_sid = pixel_consent_cookie_value.allow_sid === "1"; 784 if (allow_uid) { 785 if (window.pixel.helpers.get_cookie_value(configuration.user_cookie_name) == null) { 786 window.pixel.user_manager.create_user_cookie(); 787 } 788 event_data[configuration.user_cookie_name] = window.pixel.user_manager.get_user_cookie_values()[0]; 789 } 790 if (allow_sid) { 791 if (window.pixel.helpers.get_cookie_value(configuration.session_cookie_name) == null) { 792 window.pixel.session_manager.create_session_cookie(); 793 } 794 event_data[configuration.session_cookie_name] = window.pixel.session_manager.get_session_cookie_values()[0]; 795 } 796 797 // Add other event-level context 798 event_data["screen_height"] = screen.height || "";
799 event_data["screen_width"] = screen.width || ""; 800 event_data["user_agent"] = navigator.userAgent || ""; 801 event_data["language"] = navigator.language || ""; 802 event_data["consent"] = pixel_consent_cookie_value; 803 event_data["consent_state"] = window.pixel.consent_manager.retrieve_consent_state() || undefined; 804 805 // Trigger the main pixel event 806 window.pixel.helpers.log_debug("Sending event data to API...", "log"); 807 if (navigator.sendBeacon) { 808 navigator.sendBeacon(configuration.default_event_endpoint, JSON.stringify(event_data)); 809 window.pixel.helpers.log_debug("Event sent using sendBeacon", "log"); 810 } else { 811 var xmlhttp = new XMLHttpRequest(); 812 xmlhttp.open("POST", configuration.default_event_endpoint, true); 813 xmlhttp.setRequestHeader("Content-Type", "application/json"); 814 xmlhttp.send(JSON.stringify(event_data)); 815 window.pixel.helpers.log_debug("Event sent using XMLHttpRequest", "log"); 816 } 817 } 818 // Floodgate closed, store event behind floodgate and send ping 819 else { 820 window.pixel.helpers.log_debug("Floodgate closed, storing event behind floodgate", "log"); 821 if (configuration.allow_pings === true) { 822 //Trigger the ping 823 this.send_ping(event_name, event_data); 824 } 825 826 if (typeof sessionStorage !== "undefined") { 827 //Append to floodgate array in sessionStorage which is persisstent across pages. 828 window.pixel.floodgate_events = JSON.parse(sessionStorage.getItem(configuration.floodgate_name)) || []; 829 window.pixel.floodgate_events.push(event_data); 830 window.pixel.helpers.log_debug("Event floodgated using sessionStorage", "log"); 831 sessionStorage.setItem(configuration.floodgate_name, JSON.stringify(window.pixel.floodgate_events)); 832 } else { 833 //Append to floodgate array in JS variable which is not persisstent across pages! 834 window.pixel.floodgate_events = window.pixel.floodgate_events || []; 835 window.pixel.floodgate_events.push(event_data); 836 window.pixel.helpers.log_debug("Event floodgated using JS variable", "log"); 837 } 838 } 839 }, 840 841 // Send anonymous ping function 842 send_ping: function (event_name, event_body) { 843 var configuration = window.pixel.configuration; 844 var ping_url = configuration.default_event_endpoint.replace(/\/?$/, "/") + "ping/"; 845 var origin = window.location.href; 846 var referrer = document.referrer; 847 848 // Use sendBeacon if available 849 if (navigator.sendBeacon) { 850 var payload = JSON.stringify({ 851 origin: origin, 852 referrer: referrer, 853 event: event_name, 854 id: event_body[configuration.event_id_name], 855 }); 856 857 navigator.sendBeacon(ping_url, payload); 858 } 859 }, 860 861 // JS session definition logic 862 session_event_logic: function () { 863 var configuration = window.pixel.configuration; 864 window.pixel.helpers.log_debug("Start session logic function", "log"); 865 866 // Persisted guard because GTM can inject multiple times per page 867 if (!configuration.session_start_sent && typeof sessionStorage !== "undefined") { 868 configuration.session_start_sent = sessionStorage.getItem(configuration.session_start_sent_storage_name) === "1"; 869 } 870 871 function addSessionReason(reason) { 872 if (!configuration.session_start_reasons.includes(reason)) { 873 configuration.session_start_reasons.push(reason); 874 } 875 } 876 877 878 // Reload session exclusion 879 var nav = []; 880 if (typeof performance !== "undefined" && typeof performance.getEntriesByType === "function") { 881 nav = performance.getEntriesByType("navigation"); 882 } 883 if (nav.length > 0 && nav[0] && nav[0].type === "reload") { 884 window.pixel.helpers.log_debug("Navigation type is reload, excluding from session start", "log"); 885 return; 886 } 887 888 // Payment session exclusions 889 var payment_referrer_exclusions = [ 890 "abnamro.nl", 891 "asnbank.nl", 892 "pay.mollie.nl", 893 "mollie.com", 894 "ecommerce-gateway.mollie.com",
895 "paypal.com", 896 "klarna.com", 897 "girogate.be", 898 "snsbank.nl", 899 "rabobank.nl", 900 "knab.nl", 901 "bunq.com", 902 ".ing.nl", 903 "regiobank.nl", 904 "triodos.nl", 905 "vanlanschot.nl", 906 "moneyou.nl", 907 "multisafepay.com", 908 "agone.com", 909 "pay.nl", 910 "sips-atos.com", 911 "curopayments.net", 912 "ideal.nl", 913 "adyen.com", 914 "afterpay.nl", 915 "tikkie.me", 916 "buckaroo.nl", 917 "sisow.nl", 918 "targetpay.com", 919 "paypro.nl", 920 "icepay.nl", 921 "omnikassa.rabobank.nl", 922 "postnl.nl", 923 "billink.nl", 924 "spraypay.nl", 925 "capayable.nl", 926 "in3.nl", 927 "klarna.nl", 928 "vividmoney.nl", 929 "revolut.com", 930 "n26.com", 931 "wise.com", 932 "bancontact.com", 933 "belfius.be", 934 "cbc.be", 935 "kbc.be", 936 ".ing.be", 937 "bnpparibasfortis.be", 938 "keytradebank.be", 939 "argenta.be", 940 "fintro.be", 941 "hellobank.be", 942 "crelan.be", 943 "axabank.be", 944 "recordbank.be", 945 "sofort.com", 946 "stripe.com", 947 "worldline.com", 948 "eps-payment.eu", 949 "ogone.com", 950 "viva.com", 951 "twikey.com", 952 "hipay.com", 953 "payconiq.com", 954 "postfinance.be", 955 "six-payment-services.com", 956 ]; 957 var regex_payment = new RegExp(payment_referrer_exclusions.map(function (domain) { 958 return domain.replace(/\./g, "\\."); 959 }).join("|"), "i" 960 ); 961 962 if (regex_payment.test(document.referrer)) { 963 return; 964 } 965 966 // Referrer session evaluation 967 if (document.referrer !== "") { 968 var referrerHost = new URL(document.referrer).hostname 969 .split(".") 970 .slice(-2) 971 .join("."); 972 var currentHost = location.hostname.split(".").slice(-2).join("."); 973 if (referrerHost !== currentHost) { 974 configuration.session_start_trigger = true; 975 addSessionReason("new referrer"); 976 } 977 } else { 978 configuration.session_start_trigger = true; 979 addSessionReason("no referrer"); 980 } 981 982 // UTM session evaluation 983 if (window.location.search.indexOf("utm_") > -1) { 984 configuration.session_start_trigger = true; 985 addSessionReason("utms detected"); 986 } 987 988 // Advertising click tracker evaluation 989 var known_advertising_params = [ 990 "__hsfp", 991 "__hssc", 992 "__hstc", 993 "__s", 994 "_hsenc", 995 "_openstat", 996 "dclid", 997 "fbclid", 998 "gclid", 999 "hsCtaTracking", 1000 "mc_eid", 1001 "mkt_tok", 1002 "ml_subscriber", 1003 "ml_subscriber_hash", 1004 "msclkid", 1005 "oly_anon_id", 1006 "oly_enc_id", 1007 "rb_clickid", 1008 "s_cid", 1009 "vero_conv", 1010 "vero_id", 1011 "wickedid", 1012 "yclid", 1013 "gbraid", 1014 "scid", 1015 "ttclid", 1016 "li_fat_id", 1017 "cnvsn_id", 1018 "nclid", 1019 "clickid", 1020 "tid", 1021 ]; 1022 1023 var detected_advertising_params = []; 1024 var searchParams = window.location.search; 1025 1026 // Check for advertising parameters in the URL 1027 known_advertising_params.forEach(function (param) { 1028 if (searchParams.includes(param)) { 1029 detected_advertising_params.push(param); 1030 } 1031 }); 1032 if (detected_advertising_params.length > 0) { 1033 var known_advertising_param_present = detected_advertising_params.length > 0; 1034 window.pixel.helpers.log_debug("Detected params: " + detected_advertising_params.join(","), "log"); 1035 } 1036 1037 1038 // Add the context and click ids if they are available 1039 if (known_advertising_param_present && window.location.search.indexOf("_gl") === -1) { 1040 configuration.session_start_trigger = true; 1041 addSessionReason("advertising param detected"); 1042 window.pixel.helpers.log_debug("Advertising parameters detected", "log"); 1043 } 1044 1045 // Check if a duplicate session start is being triggered (when sessionStorage is available) 1046 var duplicate_session_start = false;
1047 if ( configuration.session_start_trigger && typeof sessionStorage !== "undefined" && configuration.floodgate_open) { 1048 var current_session_info = JSON.stringify({ 1049 reasons: configuration.session_start_reasons, 1050 referrer: document.referrer, 1051 search: window.location.search, 1052 }); 1053 var previous_session_info = sessionStorage.getItem(configuration.session_info_storage_name); 1054 // Duplicate session_start information detected. 1055 if (current_session_info === previous_session_info) { 1056 duplicate_session_start = true; 1057 } else { 1058 1059 // Otherwise just add it to the window for later placement 1060 window.pixel.session_info = JSON.stringify({ 1061 reasons: configuration.session_start_reasons, 1062 referrer: document.referrer, 1063 search: window.location.search, 1064 }); 1065 } 1066 } 1067 // Otherwise just add it to the window for later placement 1068 else { 1069 window.pixel.session_info = JSON.stringify({ 1070 reasons: configuration.session_start_reasons, 1071 referrer: document.referrer, 1072 search: window.location.search, 1073 }); 1074 } 1075 1076 // No session id exists 1077 if ( window.pixel.helpers.get_cookie_value(configuration.session_cookie_name) === null) { 1078 configuration.session_start_trigger = true; 1079 addSessionReason("no session id"); 1080 } 1081 1082 // pixel default session evaluation 1083 if (!duplicate_session_start) { 1084 if (configuration.floodgate_open && configuration.session_start_trigger) { 1085 window.pixel.session_manager.create_session_cookie(); 1086 } //else if (window.pixel.configuration.floodgate_open && window.pixel.configuration.session_start_trigger) { 1087 //window.pixel.session_manager.create_session_cookie(); 1088 //} 1089 window.pixel.helpers.log_debug( 1090 "Eligible session_start: " + configuration.session_start_trigger.toString(), "log" 1091 ); 1092 window.pixel.helpers.log_debug( 1093 "Eligible session_start reasons: " + configuration.session_start_reasons.toString(), "log" 1094 ); 1095 1096 if (configuration.session_start_trigger && !configuration.session_start_sent) { 1097 configuration.session_start_trigger = false; 1098 configuration.session_start_sent = true; 1099 if (typeof sessionStorage !== "undefined") { 1100 sessionStorage.setItem(configuration.session_start_sent_storage_name, "1"); 1101 } 1102 window.pixel.send_event("session_start", { 1103 reason: configuration.session_start_reasons.toString(), 1104 trigger_type: "front-end", 1105 } 1106 ); 1107 } 1108 } 1109 // Cover the cookie if the session cookie is gone in a duplicate session state 1110 else if ( duplicate_session_start && configuration.session_start_trigger && window.pixel.helpers.get_cookie_value(configuration.session_cookie_name ) === null && configuration.floodgate_open) { 1111 window.pixel.session_manager.create_session_cookie(); 1112 } 1113 }, 1114}; 1115 1116// Onetrust 1117// Create the Onetrust logic initialisation 1118window.pixel.consent_manager.cmp_init = function(){ 1119 // Log the selected CMP 1120 window.pixel.helpers.log_debug( 1121 "Initial consent enforcement for: OneTrust", 1122 "log" 1123 ); 1124 var onetrust_cookie = window.pixel.helpers.get_cookie_value("OptanonConsent"); 1125 if (onetrust_cookie !== null && window.pixel.helpers.get_cookie_value("OptanonAlertBoxClosed")) { 1126 var decoded_onetrust = decodeURIComponent(onetrust_cookie); 1127 var groupsMatch = decoded_onetrust.match(/groups=([^;
1127&]+)/); 1128 var allow_necessary = "0", allow_marketing = "0"; 1129 1130 if (groupsMatch) { 1131 var groups = groupsMatch[1].split(','); 1132 groups.forEach(function (group) { 1133 var parts = group.split(':'); 1134 if (parts[0] === "C0001") { 1135 allow_necessary = parts[1] === "1" ? "1" : "0"; 1136 } 1137 if (parts[0] === "C0007" || parts[0] === "C0003") { 1138 allow_marketing = parts[1] === "1" ? "1" : "0"; 1139 // Set the marketing pixel cookie value for dynamic loading of destinations 1140 window.pixel.configuration.cmp_allow_marketing = parts[1] === "1"; 1141 } 1142 }); 1143 } 1144 1145 // Persist consent signal even if groups are missing/unexpected. 1146 var encoded_value_based_on_onetrust = encodeURIComponent(JSON.stringify({ 1147 "allow_marketing": allow_marketing, 1148 "allow_pii": allow_marketing, 1149 "allow_uid": allow_necessary, 1150 "allow_sid": allow_necessary, 1151 "b": window.pixel.configuration.blocking_detected, 1152 "unix": Date.now() 1153 })); 1154 window.pixel.helpers.set_cookie( 1155 window.pixel.configuration.consent_cookie_name, 1156 encoded_value_based_on_onetrust, 1157 window.pixel.configuration.cookie_expiration_milliseconds, 1158 "/", 1159 window.pixel.helpers.get_cookie_domain(window.location.hostname) 1160 ); 1161 window.pixel.configuration.floodgate_open = true; 1162 window.pixel.configuration.cmp_update_handled = true; 1163 } 1164 window.pixel.consent_manager.cmp_update_listener("OneTrustGroupsUpdated", document); 1165}; 1166 1167// Function that adds event listeners for the chosen CMP 1168window.pixel.consent_manager.cmp_update_listener = function(cmp_update_trigger, context) { 1169 window.pixel.helpers.log_debug(("Add listener for consent update: " + cmp_update_trigger + context.toString()), "log"); 1170 context.addEventListener(cmp_update_trigger, function () { 1171 // Check current status of consent cookie 1172 var pixel_consent_cookie = window.pixel.helpers.get_cookie_value(window.pixel.configuration.consent_cookie_name); 1173 window.pixel.helpers.log_debug(("Event listener triggered with pixel consent cookie value: " + (pixel_consent_cookie || "null")), "log"); 1174 1175 // CMP update is already handled, if so, exit this function 1176 if (window.pixel.configuration.cmp_update_handled) { 1177 // Extend timeout 1178 window.pixel.consent_manager.timeout_consent_listener_updates(); 1179 return; 1180 } 1181 1182 // update pixel consent cookie 1183 window.pixel.helpers.log_debug("Trigger the initial consent enforcement after CMP update event listener", "log"); 1184 window.pixel.consent_manager.initial_consent_enforcement(); 1185 }); 1186}; 1187 1188// Check CMP consent status 1189window.pixel.consent_manager.has_explicit_cmp_consent = function(){ 1190 var has_explicit_consent = false; 1191 has_explicit_consent = window.pixel.helpers.get_cookie_value("OptanonConsent") !== null; 1192 return has_explicit_consent; 1193}; 1194 1195// Click listener for click events 1196window.pixel.click_listener = function(){ 1197 document.addEventListener("click", function(event){ 1198 window.pixel.configuration.last_interaction_unix_timestamp_ms = Date.now(); 1199 1200 // Find the closest anchor element 1201 var link = event.target.closest ? event.target.closest('a') : null; 1202 if (link && link.href) { 1203 var classes = link.className.split(' ').join(', '); // Convert classes to a comma-separated string 1204 window.pixel.send_event("link_click", { 1205 href: link.href, 1206 text: link.innerText, 1207 id: link.id, 1208 classes: classes, 1209 target: link.target, 1210 isDifferentHostname: link.hostname !== window.location.hostname 1211 }); 1212 } 1213 }); 1214}(); 1215 1216// Initialization 1217window.pixel.initialisation_sequence = function(){ 1218 // Check if the user id cookie exists 1219 if (window.pixel.helpers.get_cookie_value(window.pixel.configuration.user_cookie_name) === null) { 1220 // Check if consent is already provided, but only pixel is not initialized properly yet 1221 var has_explicit_cmp_consent = window.pixel.consent_manager.has_explicit_cmp_consent(window.pixel.configuration.cmp_selection); 1222 if(has_explicit_cmp_consent){
1223 // Do nothing, cmp consent is present by default 1224 1225 // window.pixel.helpers.log_debug("Explicit CMP consent found but no user id, so set user cookie", "log"); 1226 // window.pixel.user_manager.create_user_cookie(); 1227 // window.pixel.consent_manager.initial_consent_enforcement(); 1228 // window.pixel.session_event_logic(); 1229 } 1230 1231 // pixel is not initialized yet, there is no user id and no permission for placement before consent. There is also no explicit consent found for the CMP yet. Floodgate everything 1232 else { 1233 window.pixel.session_event_logic(); 1234 window.pixel.consent_manager.initial_consent_enforcement(); 1235 // window.pixel.session_event_logic(); 1236 } 1237 } 1238 else { 1239 window.pixel.session_event_logic(); 1240 window.pixel.consent_manager.initial_consent_enforcement(); 1241 // window.pixel.consent_manager.evaluate_consent_floodgate(); 1242 // window.pixel.session_event_logic(); 1243 } 1244}; 1245 1246window.pixel.initialisation_sequence(); 1247 1248window.pixel_event = function(event_name, context, user, ecommerce, target_params){ 1249 try { 1250 window.pixel.consent_manager.initial_consent_enforcement(); 1251 window.pixel.send_event(event_name, context, user, ecommerce, target_params) 1252 } catch (error) { 1253 console.error("Error sending event:", error.message); 1254 } 1255}
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.