1(function () { 2 "use strict"; 3 4 var cfg = window.TTLTConsent || {}; 5 var cookieName = cfg.cookieName || "cf_consent"; 6 var cookieDomain = cfg.cookieDomain || ".tomitribe.com"; 7 var gdprCountries = cfg.gdprCountries || []; 8 // Server hint only â the HTML this rides in may be cached from another visitor's 9 // region. The real region comes from Cloudflare's per-request /cdn-cgi/trace. 10 var regionHint = String(cfg.regionHint || document.documentElement.getAttribute("data-consent-region") || "gdpr").toLowerCase(); 11 var region = regionHint; 12 var isGdpr = true; 13 14 function escapeCookieName(name) { 15 return name.replace(/([.*+?^${}()|[\]\\])/g, "\\$1"); 16 } 17 18 function getCookie(name) { 19 var match = document.cookie.match(new RegExp("(^|;)\\s*" + escapeCookieName(name) + "\\s*=\\s*([^;]+)")); 20 if (!match) { 21 return null; 22 } 23 try { 24 return decodeURIComponent(match.pop()); 25 } catch (err) { 26 return null; 27 } 28 } 29 30 function setCookie(name, value, days, domain) { 31 var date = new Date(); 32 date.setTime(date.getTime() + days * 864e5); 33 document.cookie = 34 name + 35 "=" + 36 encodeURIComponent(value) + 37 ";expires=" + 38 date.toUTCString() + 39 ";path=/;domain=" + 40 domain + 41 ";SameSite=Strict;Secure"; 42 } 43 44 function safeSessionGet(key) { 45 try { 46 return window.sessionStorage ? window.sessionStorage.getItem(key) : null; 47 } catch (err) { 48 return null; 49 } 50 } 51 52 function safeSessionSet(key, value) { 53 try { 54 if (window.sessionStorage) { 55 window.sessionStorage.setItem(key, value); 56 } 57 } catch (err) {} 58 } 59 60 function consentValue(value) { 61 return value ? "granted" : "denied"; 62 } 63 64 function parseConsentObject(value) { 65 if ( 66 value && 67 typeof value.analytics === "boolean" && 68 typeof value.advertising === "boolean" 69 ) { 70 return { 71 analytics: value.analytics, 72 advertising: value.advertising, 73 }; 74 } 75 return null; 76 } 77 78 function parseConsentCookie() { 79 var cookie = getCookie(cookieName); 80 if (!cookie) { 81 return null; 82 } 83 try { 84 return parseConsentObject(JSON.parse(cookie)); 85 } catch (err) { 86 return null; 87 } 88 } 89 90 function getRegionalConsent() { 91 return { 92 analytics: !isGdpr, 93 advertising: !isGdpr, 94 }; 95 } 96 97 function getInitialConsent() { 98 return parseConsentCookie() || getRegionalConsent(); 99 } 100 101 function pushConsentUpdate(analytics, advertising) { 102 window.dataLayer = window.dataLayer || []; 103 window.gtag = 104 window.gtag || 105 function () { 106 window.dataLayer.push(arguments); 107 }; 108 window.gtag("consent", "update", { 109 ad_storage: consentValue(advertising), 110 analytics_storage: consentValue(analytics), 111 ad_user_data: consentValue(advertising), 112 ad_personalization: consentValue(advertising), 113 }); 114 } 115 116 function updateConsent(analytics, advertising) { 117 var payload = JSON.stringify({ advertising: !!advertising, analytics: !!analytics });
118 setCookie(cookieName, payload, 365, cookieDomain); 119 pushConsentUpdate(analytics, advertising); 120 try { 121 if (window.zaraz && window.zaraz.consent) { 122 window.zaraz.consent.set("analytics", !!analytics); 123 window.zaraz.consent.set("advertising", !!advertising); 124 if (analytics || advertising) { 125 window.zaraz.consent.sendQueuedEvents(); 126 } 127 } 128 } catch (err) {} 129 } 130 131 // ---- region resolution ---------------------------------------------------- 132 // Country â region with the same fail-closed rule as the server: an EEA/UK/CH 133 // country is GDPR, an unknown or placeholder code (XX, T1, empty) is GDPR, any 134 // other real country is non-GDPR (opt-out model). 135 function regionForCountry(country) { 136 var code = String(country || "").trim().toUpperCase(); 137 if (!/^[A-Z]{2}$/.test(code) || code === "XX" || code === "T1") { 138 return "gdpr"; 139 } 140 return gdprCountries.indexOf(code) !== -1 ? "gdpr" : "us"; 141 } 142 143 function resolveRegion() { 144 var cached = safeSessionGet("tt_region"); 145 if (cached) { 146 return Promise.resolve(String(cached).toLowerCase()); 147 } 148 if (!window.fetch) { 149 return Promise.resolve(regionHint); 150 } 151 return fetch("/cdn-cgi/trace", { cache: "no-store", credentials: "omit" }) 152 .then(function (res) { 153 return res.ok ? res.text() : ""; 154 }) 155 .then(function (text) { 156 var match = /(?:^|\n)loc=([A-Za-z0-9]+)/.exec(text || ""); 157 var resolved = match ? regionForCountry(match[1]) : regionHint; 158 safeSessionSet("tt_region", resolved); 159 return resolved; 160 }) 161 .catch(function () { 162 return regionHint; 163 }); 164 } 165 166 function removeBanner() { 167 var banner = document.getElementById("ttlt-consent-banner"); 168 if (banner && banner.parentNode) { 169 banner.parentNode.removeChild(banner); 170 } 171 } 172 173 function makeButton(className, text) { 174 var button = document.createElement("button"); 175 button.type = "button"; 176 button.className = className; 177 button.textContent = text; 178 return button; 179 } 180 181 function makeRow(id, label, description, checked) { 182 var row = document.createElement("div"); 183 row.className = "ttlt-consent-row"; 184 var text = document.createElement("label"); 185 text.htmlFor = id; 186 var labelEl = document.createElement("span"); 187 labelEl.className = "ttlt-consent-label"; 188 labelEl.textContent = label; 189 var descEl = document.createElement("span"); 190 descEl.className = "ttlt-consent-desc"; 191 descEl.textContent = description; 192 text.appendChild(labelEl); 193 text.appendChild(descEl); 194 var input = document.createElement("input"); 195 input.type = "checkbox"; 196 input.id = id; 197 input.checked = !!checked; 198 row.appendChild(text); 199 row.appendChild(input); 200 return row; 201 } 202 203 function render() { 204 if (document.getElementById("ttlt-consent-banner")) { 205 return; 206 } 207 if (isGdpr && getCookie(cookieName)) { 208 return; 209 } 210 if (!isGdpr && safeSessionGet("ttlt_consent_dismissed")) { 211 return; 212 } 213 214 var initialConsent = getInitialConsent(); 215 var banner = document.createElement("div"); 216 banner.id = "ttlt-consent-banner"; 217 banner.setAttribute("role", "dialog"); 218 banner.setAttribute("aria-label", "Cookie consent"); 219 220 var grid = document.createElement("div"); 221 grid.className = "ttlt-consent-grid"; 222 223 var copy = document.createElement("p"); 224 copy.className = "ttlt-consent-text"; 225 copy.innerHTML = isGdpr 226 ? 'We use cookies to enhance your experience and analyze site traffic. See our <a href="/legal/privacy-policy/">Cookie Policy</a>.' 227 : 'We use cookies to enhance your experience and analyze site traffic. By continuing to browse, you accept our <a href="/legal/privacy-policy/">Cookie Policy</a>.'; 228 229 var actions = document.createElement("div"); 230 actions.className = "ttlt-consent-actions"; 231 var prefs = makeButton("ttlt-consent-preferences", "Cookie Preferences"); 232 prefs.setAttribute("aria-controls", "ttlt-consent-preferences-panel"); 233 prefs.setAttribute("aria-expanded", "false"); 234 actions.appendChild(prefs); 235 236 var decline = null; 237 var accept = null; 238 var dismiss = null; 239 if (isGdpr) { 240 decline = makeButton("ttlt-consent-secondary", "Decline"); 241 accept = makeButton("ttlt-consent-primary", "Accept"); 242 actions.appendChild(decline); 243 actions.appendChild(accept); 244 } else {
245 dismiss = makeButton("ttlt-consent-dismiss", "Ã"); 246 dismiss.setAttribute("aria-label", "Dismiss"); 247 actions.appendChild(dismiss); 248 } 249 250 var panel = document.createElement("div"); 251 panel.className = "ttlt-consent-panel"; 252 panel.id = "ttlt-consent-preferences-panel"; 253 panel.appendChild(makeRow("ttlt-consent-analytics", "Analytics", "Helps us understand how visitors interact with the site.", initialConsent.analytics)); 254 panel.appendChild(makeRow("ttlt-consent-advertising", "Advertising", "Measures campaign performance and supports relevant ads.", initialConsent.advertising)); 255 var save = makeButton("ttlt-consent-save", "Save Preferences"); 256 panel.appendChild(save); 257 258 grid.appendChild(copy); 259 grid.appendChild(actions); 260 grid.appendChild(panel); 261 banner.appendChild(grid); 262 document.body.appendChild(banner); 263 264 prefs.addEventListener("click", function () { 265 var isOpen = panel.classList.toggle("is-open"); 266 prefs.setAttribute("aria-expanded", isOpen ? "true" : "false"); 267 }); 268 save.addEventListener("click", function () { 269 updateConsent( 270 document.getElementById("ttlt-consent-analytics").checked, 271 document.getElementById("ttlt-consent-advertising").checked 272 ); 273 if (!isGdpr) { 274 safeSessionSet("ttlt_consent_dismissed", "1"); 275 } 276 removeBanner(); 277 }); 278 if (accept) { 279 accept.addEventListener("click", function () { 280 updateConsent(true, true); 281 removeBanner(); 282 }); 283 } 284 if (decline) { 285 decline.addEventListener("click", function () { 286 updateConsent(false, false); 287 removeBanner(); 288 }); 289 } 290 if (dismiss) { 291 dismiss.addEventListener("click", function () { 292 safeSessionSet("ttlt_consent_dismissed", "1"); 293 removeBanner(); 294 }); 295 } 296 } 297 298 function start() { 299 var stored = parseConsentCookie(); 300 resolveRegion().then(function (resolved) { 301 region = resolved; 302 isGdpr = region === "gdpr"; 303 if (!stored && !isGdpr) { 304 // Opt-out model outside the GDPR region: record the default and make the 305 // granted state explicit for Google (the region default already grants). 306 updateConsent(true, true); 307 } 308 render(); 309 }); 310 } 311 312 if (document.readyState === "loading") { 313 document.addEventListener("DOMContentLoaded", start); 314 } else { 315 start(); 316 } 317})();
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.