1<!DOCTYPE html> 2<html lang="en" dir="ltr" class="h-100"> 3<head> 4 <title>Sign in - Cool Popup</title> 5 <base href="https://dash.coolpopup.com/"> 6 <meta charset="UTF-8"> 7 <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" /> 8 9 <meta name="theme-color" content="#FD7272"/> 10 11 <meta name="apple-mobile-web-app-capable" content="yes"> 12 <meta name="mobile-web-app-capable" content="yes"> 13 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> 14 15 16 <link rel="apple-touch-startup-image" href="https://dash.coolpopup.com/pwa-splash-generator?size=750x1334&icon=6330bfe7531e0355f46cccd6428bde57.png&color=" media="(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2)"> 17 <link rel="apple-touch-startup-image" href="https://dash.coolpopup.com/pwa-splash-generator?size=1170x2532&icon=6330bfe7531e0355f46cccd6428bde57.png&color=" media="(device-width: 390px) and (device-height: 844px) and (-webkit-device-pixel-ratio: 3)"> 18 <link rel="apple-touch-startup-image" href="https://dash.coolpopup.com/pwa-splash-generator?size=1179x2556&icon=6330bfe7531e0355f46cccd6428bde57.png&color=" media="(device-width: 393px) and (device-height: 852px) and (-webkit-device-pixel-ratio: 3)"> 19 <link rel="apple-touch-startup-image" href="https://dash.coolpopup.com/pwa-splash-generator?size=1290x2796&icon=6330bfe7531e0355f46cccd6428bde57.png&color=" media="(device-width: 430px) and (device-height: 932px) and (-webkit-device-pixel-ratio: 3)"> 20 <link rel="apple-touch-startup-image" href="https://dash.coolpopup.com/pwa-splash-generator?size=1536x2048&icon=6330bfe7531e0355f46cccd6428bde57.png&color=" media="(device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2)"> 21 <link rel="apple-touch-startup-image" href="https://dash.coolpopup.com/pwa-splash-generator?size=2048x2732&icon=6330bfe7531e0355f46cccd6428bde57.png&color=" media="(device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2)"> 22 23 <link rel="manifest" href="https://dash.coolpopup.com/uploads/pwa/manifest.json" /> 24 25 <link rel="canonical" href="https://dash.coolpopup.com/login" /> 26 27 28 <link rel="alternate" href="https://dash.coolpopup.com/login" hreflang="x-default" /> 29 <link rel="alternate" href="https://dash.coolpopup.com/fr/login" hreflang="fr" /> 30 <link rel="alternate" href="https://dash.coolpopup.com/es/login" hreflang="es" /> 31 32 <link href="https://cdn.coolpopup.com/uploads/main/291664e6ebaffdbf25960d50f7fb70b0.svg" rel="icon" /> 33 34 <link href="https://assets.coolpopup.com/themes/cptheme/assets/css/bootstrap.min.css?v=5321" id="css_theme_style" rel="stylesheet" media="screen,print"> 35 <link href="https://assets.coolpopup.com/themes/cptheme/assets/css/custom.css?v=5321" rel="stylesheet" media="screen"> 36 37 38 39 <!-- Pixel Code - https://dash.coolpopup.com/ -->
40<script defer src="https://dash.coolpopup.com/pixel/FhS0ck4gGtEvS0vmErOfxUelPJgv4GDA"></script>
40 41<!-- END Pixel Code --> 42
43<script> 44function loadCCWidget(){(new window["click-connector-widget"]).mount({})}function loadCCScript(){var t=document.createElement("script");t.id="cc-widget-script",t.setAttribute("data-widget-id","1adf10-411d0"),t.type="text/javascript",t.defer=!0,t.addEventListener("load",(function(t){loadCCWidget()})),t.src="https://widget.clickconnector.app/widget.js",document.getElementsByTagName("head")[0].appendChild(t)}loadCCScript(); 45</script>
45 46
47<script 48 src="https://pushlapgrowth.com/affiliate-tracker.js" 49 data-affiliate data-program-id="9e3d5e96-8c7e-4228-acad-12c6239681cf" 50 async></script>
vendor: 2 bytes, line 50
50
51<script 52 src="https://www.pushlapgrowth.com/affiliate-widget.js" 53 data-affiliate-program-id="9e3d5e96-8c7e-4228-acad-12c6239681cf" 54 data-user-email="" 55></script>
55 56 57<!-- Meta Pixel Code -->
58<script>
vendor: 408 bytes, lines 58-67
58 59!function(f,b,e,v,n,t,s) 60{if(f.fbq)return;n=f.fbq=function(){n.callMethod? 61n.callMethod.apply(n,arguments):n.queue.push(arguments)}; 62if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0'; 63n.queue=[];t=b.createElement(e);t.async=!0; 64t.src=v;s=b.getElementsByTagName(e)[0]; 65s.parentNode.insertBefore(t,s)}(window, document,'script', 66'https://connect.facebook.net/en_US/fbevents.js'); 67fbq('init', '
671403802591248070
vendor: 32 bytes, lines 67-68
67'); 68fbq('track', 'PageView');
69</script>
69 70<noscript><img height="1" width="1" style="display:none" 71src="https://www.facebook.com/tr?id=1403802591248070&ev=PageView&noscript=1" 72/></noscript> 73<!-- End Meta Pixel Code --> 74 <style>body { 75 min-height: 100vh; 76 display: flex; 77 flex-direction: column; 78} 79.container { 80 max-width: 1500px !important; 81} 82.text-truncate { 83 overflow: unset; 84} 85.header { 86 padding: 1rem 0; 87} 88.footer { 89 display: flex; 90 flex-direction: row; 91 position: sticky; 92 top: calc(100% - 2rem); 93 margin-top: 2rem; 94 padding-top: 1rem; 95} 96.table-custom td { 97 padding: 1rem 1rem; 98} 99.pre-custom { 100 padding: 1rem; 101} 102form[name='create_notification'] div.mt-4 { 103 position: -webkit-sticky; 104 position: sticky; 105 bottom: 0; 106 padding: 1rem; 107 background: #ebebeb; 108 max-width: 50%; 109 border: lightgray 1px solid; 110 border-radius: 5px; 111 box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); 112} 113.mt-5 { 114 margin-top: 1.5rem !important; 115}</style> 116 </head> 117 118<body class=" bg-gray-50 login-background " data-theme-style="light"> 119 <!-- TWIPLA Tracking Code for https://dash.coolpopup.com/dashboard -->
119<script>(function(v,i,s,a,t){v[t]=v[t]||function(){(v[t].v=v[t].v||[]).push(arguments)};if(!v._visaSettings){v._visaSettings={}}v._visaSettings[a]={v:'1.0',s:a,a:'1',t:t};var b=i.getElementsByTagName('body')[0];var p=i.createElement('script');p.defer=1;p.async=1;p.src=s+'?s='+a;b.appendChild(p)})(window,document,'//app-worker.visitor-analytics.io/main.js','079a5bd0-b93f-11ef-83dd-3ee91221b999','va')</script>
119<!-- TWIPLA Tracking Code for https://dash.coolpopup.com/dashboard --> 120 121<!-- Usetiful script start --> 122
122<script> 123 (function (w, d, s) { 124 var a = d.getElementsByTagName('head')[0]; 125 var r = d.createElement('script'); 126 r.async = 1; 127 r.src = s; 128 r.setAttribute('id', 'usetifulScript'); 129 r.dataset.token = "068eed677c49892f44f04d6d33f54cc6"; // This is your unique USETIFUL token. Donât change it. 130 a.appendChild(r); 131 })(window, document, "https://www.usetiful.com/dist/usetiful.js");</script>
131 132<!-- Usetiful script end --> 133 134<!-- Rover script start -->
135<script 136 src="https://rover.rtrvr.ai/embed.js?v=8d27daf1-bbe2-4210-841d-04289cee70bb" 137 async 138 data-site-id="Dash-IKM9gg" 139 data-public-key="pk_site_nyiIEtvjjrhbRFbDH1DZsXYBDtQvSpRIckamp37jrs8" 140 data-site-key-id="8d27daf1-bbe2-4210-841d-04289cee70bb" 141 data-analytics-enabled="true" 142 data-analytics-api-base="https://roverbook.rtrvr.ai" 143 data-analytics-debug="false"></script>
143 144<template data-rover-agent-action="v2" data-rover-a2w="https://agent.rtrvr.ai/v2/a2w/runs">{"v":2,"a2w":"https://agent.rtrvr.ai/v2/a2w/runs","browser":{"prompt":"rover","shortcutId":"rover_shortcut","playbookId":"rover_playbook","engagementKind":"rover_kind"}}</template> 145<!-- Rover script end --> 146 147 148 149 150 151 152 <div id="spotlight_wrapper" class="spotlight-wrapper d-none" aria-hidden="true"> 153 <div class="container spotlight-modal"> 154 155 <form id="spotlight_form" action="" method="get" role="form"> 156 <input type="hidden" name="global_token" value="b710d0facbe34e796511de62be84b4868392a4d8c927c4aa373a21542182d1c1" /> 157 158 <input id="spotlight_search" type="search" name="search" class="form-control" required="required" autocomplete="off" placeholder="ð Search & go to a page..." aria-label="Search" /> 159 160 <div id="spotlight_results" class="spotlight-results mt-3"></div> 161 162 <div id="spotlight_no_data" class="my-3 p-3 bg-gray-50 rounded-2x position-relative text-center" style="display:none;"> 163 <span class="text-muted">No data available</span> 164 </div> 165 </form> 166 </div> 167 </div> 168 169 170 171<main class="altum-animate altum-animate-fill-none altum-animate-fade-in py-6"> 172 <div class="container"> 173 <div class="d-flex flex-column align-items-center"> 174 <div class="col-xs-12 col-md-9 col-lg-7 col-xl-5"> 175 176 <div class="mb-5 text-center"> 177 <a href="https://dash.coolpopup.com/" target="_blank" rel="noopener noreferrer" class="text-decoration-none text-dark"> 178 <img src="https://cdn.coolpopup.com/uploads/main/d85f2a3ab65c92e229f9a5ac7cd2c8df.svg" class="img-fluid navbar-logo" alt="Website logo" /> 179 </a> 180 </div> 181 182 <div class="card rounded-2x"> 183 <div class="card-body p-5"> 184 185<div class="alert-container"></div> 186 187<h1 class="h5">Sign in</h1> 188
189<script> 190console.log('Google One Tap Debug:', { 191 client_id: 'SET', 192 is_localhost: false, 193 host: 'dash.coolpopup.com' 194}); 195</script>
195 196 <!-- Google One Tap for Signin -->
197<script src="https://assets.coolpopup.com/themes/cptheme/assets/js/google-one-tap-handler.js"></script>
197 198 199<!-- Define callback immediately to prevent GSI race condition -->
200<script> 201 window.handleGoogleOneTap = function(response) { 202 if (typeof GoogleOneTapHandler !== 'undefined') { 203 GoogleOneTapHandler.handleResponse(response); 204 } else { 205 console.error('[GoogleOneTap] Handler not loaded yet'); 206 } 207 }; 208</script>
208 209
210<script src="https://accounts.google.com/gsi/client" async defer></script>
210 211 212<div id="g_id_onload" 213 data-client_id="691887830438-bkfe3e8rdd3qml2dkotelij09k9ct7et.apps.googleusercontent.com" 214 data-context="signin" 215 data-ux_mode="popup" 216 data-auto_prompt="true" 217 data-itp_support="true" 218 data-callback="handleGoogleOneTap" 219 data-auto_select="false" 220 data-cancel_on_tap_outside="false"> 221</div> 222
223<script> 224// Initialize immediately - do not wait for DOMContentLoaded 225if (typeof GoogleOneTapHandler !== 'undefined') { 226 GoogleOneTapHandler.init({"context":"signin","redirectUrl":"redirect=dashboard","successMessage":"Welcome back, %s.","errorMessage":"Your login combination is invalid.","backendUrl":"https:\/\/dash.coolpopup.com\/google-one-tap","defaultRedirect":"https:\/\/dash.coolpopup.com\/dashboard","debug":false}); 227} else { 228 console.error('[GoogleOneTap] Handler script failed to load'); 229} 230</script>
230 231 232<!-- Fallback button container (hidden by default) --> 233<div id="google-one-tap-signin-button" class="d-none"></div> 234 235<form action="" method="post" class="mt-4" role="form"> 236 237 <div class="form-group"> 238 <label for="email">Email</label> 239 <input id="email" type="text" name="email" class="form-control " value="" required="required" autofocus="autofocus" /> 240 </div> 241 242 <div class="form-group" data-password-toggle-view data-password-toggle-view-show="Show" data-password-toggle-view-hide="Hide"> 243 <label for="password">Password</label> 244 <input id="password" type="password" name="password" class="form-control " value="" required="required" /> 245 </div> 246 247 248 <div class="d-flex flex-column flex-md-row justify-content-between align-items-md-center"> 249 <div class="custom-control custom-checkbox" data-toggle="tooltip" title="A browser cookie will be used to remember you for 30 days on this browser." data-tooltip-hide-on-click> 250 <input type="checkbox" name="rememberme" class="custom-control-input" id="rememberme" > 251 <label class="custom-control-label" for="rememberme"><small class="text-muted">Remember me</small></label> 252 </div> 253 254 <small class="text-muted"> 255 <a href="https://dash.coolpopup.com/lost-password?redirect=dashboard" class="text-muted">Lost password</a> 256 / <a href="https://dash.coolpopup.com/resend-activation?redirect=dashboard" class="text-muted" role="button">Resend activation</a> 257 </small> 258 </div> 259 260 <div class="form-group mt-4"> 261 <button type="submit" name="submit" class="btn btn-primary btn-block my-1" >Login</button> 262 </div> 263 264 <hr class="border-gray-100 my-3" /> 265 266 <div> 267 <div class="mt-2"> 268 <a href="https://dash.coolpopup.com/login/facebook-initiate?redirect=dashboard" class="btn btn-light btn-block" data-provider="facebook"> 269 <img src="https://assets.coolpopup.com/themes/cptheme/assets/images/facebook.svg" class="mr-1" /> 270 Sign in with Facebook </a> 271 </div> 272 <div class="mt-2"> 273 <a href="https://dash.coolpopup.com/login/google-initiate?redirect=dashboard" class="btn btn-light btn-block" data-provider="google"> 274 <img src="https://assets.coolpopup.com/themes/cptheme/assets/images/google.svg" class="mr-1" /> 275 Sign in with Google </a> 276 </div> 277 <div class="mt-2"> 278 <a href="https://dash.coolpopup.com/login/shopify-initiate?redirect=dashboard" class="btn btn-light btn-block" data-provider="shopify"> 279 <img src="https://assets.coolpopup.com/themes/cptheme/assets/images/shopify.svg" class="mr-1" /> 280 Sign in with Shopify </a> 281 </div> 282 </div> 283 </form> 284 285 <div class="mt-5 text-center text-muted"> 286 Don't have an account? <a href="https://dash.coolpopup.com/register?redirect=dashboard" class="font-weight-bold">Register</a></a> 287 </div> 288 289 290 291 </div> 292 </div> 293 294 </div> 295 </div> 296 </div> 297</main> 298 299 300 301<input type="hidden" name="global_site_url" value="https://dash.coolpopup.com/" /> 302<input type="hidden" name="global_url" value="https://dash.coolpopup.com/" /> 303<input type="hidden" name="global_token" value="b710d0facbe34e796511de62be84b4868392a4d8c927c4aa373a21542182d1c1" /> 304<input type="hidden" name="global_number_decimal_point" value="." /> 305<input type="hidden" name="global_number_thousands_separator" value="," /> 306
307<script> 308 'use strict'; 309 310 /* Some global variables */ 311 window.altum = {}; 312 let global_token = document.querySelector('input[name="global_token"]').value; 313 let site_url = document.querySelector('input[name="global_site_url"]').value; 314 let url = document.querySelector('input[name="global_url"]').value; 315 let decimal_point = document.querySelector('[name="global_number_decimal_point"]').value; 316 let thousands_separator = document.querySelector('[name="global_number_thousands_separator"]').value; 317</script>
317 318 319
319<script src="https://assets.coolpopup.com/themes/cptheme/assets/js/libraries/jquery.slim.min.js?v=5321"></script>
319 320
320<script src="https://assets.coolpopup.com/themes/cptheme/assets/js/libraries/popper.min.js?v=5321"></script>
320 321
321<script src="https://assets.coolpopup.com/themes/cptheme/assets/js/libraries/bootstrap.min.js?v=5321"></script>
321 322
322<script src="https://assets.coolpopup.com/themes/cptheme/assets/js/custom.js?v=5321"></script>
322 323
323<script src="https://assets.coolpopup.com/themes/cptheme/assets/js/libraries/fontawesome.min.js?v=5321"></script>
323 324
324<script src="https://assets.coolpopup.com/themes/cptheme/assets/js/libraries/fontawesome-solid.min.js?v=5321"></script>
324 325
325<script src="https://assets.coolpopup.com/themes/cptheme/assets/js/libraries/fontawesome-brands.modified.js?v=5321"></script>
325 326 327
327<script type="application/ld+json"> 328 { 329 "@context": "https://schema.org", 330 "@type": "BreadcrumbList", 331 "itemListElement": [ 332 { 333 "@type": "ListItem", 334 "position": 1, 335 "name": "Increase Conversions & Site Growth", 336 "item": "https://dash.coolpopup.com/" 337 }, 338 { 339 "@type": "ListItem", 340 "position": 2, 341 "name": "Sign in", 342 "item": "https://dash.coolpopup.com/login" 343 } 344 ] 345 } 346 </script>
346 347
347<script> 348 'use strict'; 349 350 document.querySelectorAll('[data-set-language]').forEach(element => element.addEventListener('click', event => { 351 let language = event.currentTarget.getAttribute('data-set-language'); 352 set_cookie(`set_language`, language, 90, "\/"); 353 })); 354 </script>
354 355
355<script> 356 'use strict'; 357 358 let switch_theme_style = document.querySelector('#switch_theme_style'); 359 360 if(switch_theme_style) { 361 switch_theme_style.addEventListener('click', event => { 362 let theme_style = document.querySelector('body[data-theme-style]').getAttribute('data-theme-style'); 363 let new_theme_style = theme_style == 'light' ? 'dark' : 'light'; 364 365 /* Set a cookie with the new theme style */ 366 set_cookie(`theme_style`, new_theme_style, 90, "\/"); 367 368 /* Change the css and button on the page */ 369 let css = document.querySelector(`#css_theme_style`); 370 371 document.querySelector(`body[data-theme-style]`).setAttribute('data-theme-style', new_theme_style); 372 373 switch (new_theme_style) { 374 case 'dark': 375 css.setAttribute('href', "https:\/\/assets.coolpopup.com\/themes\/cptheme\/assets\/css\/bootstrap-dark.min.css?v=5321"); 376 document.body.classList.add('cc--darkmode'); 377 break; 378 379 case 'light': 380 css.setAttribute('href', "https:\/\/assets.coolpopup.com\/themes\/cptheme\/assets\/css\/bootstrap.min.css?v=5321"); 381 document.body.classList.remove('cc--darkmode'); 382 break; 383 } 384 385 /* Refresh the logo/title */ 386 document.querySelectorAll('[data-logo]').forEach(element => { 387 let new_brand_value = element.getAttribute(`data-${new_theme_style}-value`); 388 let new_brand_class = element.getAttribute(`data-${new_theme_style}-class`); 389 let new_brand_tag = element.getAttribute(`data-${new_theme_style}-tag`) 390 let new_brand_html = new_brand_tag == 'img' ? `<img src="${new_brand_value}" class="${new_brand_class}" alt="Website logo" />` : `<${new_brand_tag} class="${new_brand_class}">${new_brand_value}</${new_brand_tag}>`; 391 element.innerHTML = new_brand_html; 392 }); 393 394 395 document.querySelector(`#switch_theme_style`).setAttribute('data-original-title', document.querySelector(`#switch_theme_style`).getAttribute(`data-title-theme-style-${theme_style}`)); 396 document.querySelector(`#switch_theme_style [data-theme-style="${new_theme_style}"]`).classList.remove('d-none'); 397 document.querySelector(`#switch_theme_style [data-theme-style="${theme_style}"]`).classList.add('d-none'); 398 399 if (typeof bootstrap !== 'undefined' && typeof bootstrap.Tooltip === 'function' && typeof Popper !== 'undefined') { 400 $(`#switch_theme_style`).tooltip('hide').tooltip('show'); 401 } 402 403 event.preventDefault(); 404 }); 405 406 document.addEventListener('keydown', event => { 407 if((event.ctrlKey || event.metaKey) && event.key === 'i') { 408 event.preventDefault(); 409 switch_theme_style.click(); 410 411 if (typeof bootstrap !== 'undefined' && typeof bootstrap.Tooltip === 'function' && typeof Popper !== 'undefined') { 412 $(`#switch_theme_style`).tooltip('hide'); 413 } 414 } 415 }); 416 } 417</script>
417 418
418<script src="https://assets.coolpopup.com/themes/cptheme/assets/js/libraries/cookieconsent.js?v=5321"></script>
418 419 <link href="https://assets.coolpopup.com/themes/cptheme/assets/css/libraries/cookieconsent.css?v=5321" rel="stylesheet" media="screen"> 420 <style> 421 :root { 422 --cc-font-family: inherit; 423 --cc-bg: hsla(0, 0%, 100%, 90%); 424 --cc-separator-border-color: transparent; 425 426 --cc-modal-border-radius: var(--border-radius); 427 --cc-btn-border-radius: var(--border-radius); 428 429 --cc-primary-color:var(--gray-700); 430 --cc-secondary-color:var(--gray-600); 431 432 --cc-btn-primary-color: var(--white); 433 --cc-btn-primary-bg: var(--primary); 434 --cc-btn-primary-hover-bg: var(--primary-600); 435 --cc-btn-primary-color-bg: var(--white); 436 --cc-btn-primary-hover-color: var(--white); 437 438 --cc-btn-secondary-bg:var(--gray-300); 439 --cc-btn-secondary-hover-bg:var(--gray-400); 440 441 --cc-btn-secondary-hover-color: var(--black); 442 --cc-btn-secondary-hover-border-color: var(--cc-btn-secondary-hover-bg); 443 } 444 445 .cc--darkmode { 446 --cc-bg: hsla(0, 0%, 0%, 90%); 447 --cc-separator-border-color: transparent; 448 } 449 </style> 450 451
451<script> 452 'use strict'; 453 454 window.addEventListener('load', () => { 455 let language_code = document.documentElement.getAttribute('lang'); 456 let language_direction = document.documentElement.getAttribute('dir'); 457 let translations = {}; 458 459 translations[language_code] = { 460 consentModal: { 461 title: "We use cookies \ud83c\udf6a", 462 description: "Hi, this website uses essential cookies to ensure its proper operation and tracking cookies to understand how you interact with it. The latter will be set only after consent.", 463 acceptAllBtn: "Accept all", 464 acceptNecessaryBtn: "Reject all", 465 showPreferencesBtn: "Customize", 466 }, 467 468 preferencesModal: { 469 title: "Cookie preferences", 470 acceptAllBtn: "Accept all", 471 acceptNecessaryBtn: "Reject all", 472 savePreferencesBtn: "Save settings", 473 closeIconLabel: "Close", 474 sections: [ 475 { 476 title: "Cookie usage \ud83d\udce2", 477 description: "We use cookies to ensure the basic functionalities of the website and to enhance your online experience. You can choose for each category to opt-in\/out whenever you want. For more details relative to cookies and other sensitive data, please read the full <a href=\"https:\/\/dash.coolpopup.com\/page\/privacy-policy\" class=\"cc-link\">privacy policy<\/a>." }, 478 479 { 480 title: "Strictly necessary cookies", 481 description: "These cookies are essential for the proper functioning of my website. Without these cookies, the website would not work properly.", 482 linkedCategory: 'necessary' 483 }, 484 485 { 486 title: "Performance and Analytics cookies", 487 description: "These cookies allow the website to remember the choices you have made in the past.", 488 linkedCategory: 'analytics' 489 }, 490 491 { 492 title: "Advertisement and Targeting cookies", 493 description: "These cookies collect information about how you use the website, which pages you visited and which links you clicked on. All of the data is anonymized and cannot be used to identify you.", 494 linkedCategory: 'targeting' 495 }, 496 ] 497 } 498 }; 499 500 CookieConsent.run({ 501 categories: { 502 necessary: { 503 enabled: true, 504 readOnly: true, 505 }, 506 analytics: {}, 507 targeting: {}, 508 }, 509 510 language: { 511 rtl: language_direction == 'rtl' ? language_code : null, 512 default: language_code, 513 autoDetect: 'document', 514 translations 515 }, 516 517 onFirstConsent: () => { 518 const preferences = CookieConsent.getUserPreferences(); 519 window.dispatchEvent(new CustomEvent('cookie_consent_update', { detail: { accepted_categories: preferences.acceptedCategories } })); 520 521 if(!get_cookie('cookie_consent_logged')) { 522 navigator.sendBeacon(`${url}cookie-consent`, JSON.stringify({global_token, level: preferences.acceptedCategories})); 523 set_cookie('cookie_consent_logged', '1', 182, "\/"); 524 } 525 }, 526 527 onChange: () => { 528 const preferences = CookieConsent.getUserPreferences(); 529 window.dispatchEvent(new CustomEvent('cookie_consent_update', { detail: { accepted_categories: preferences.acceptedCategories } })); 530 531 navigator.sendBeacon(`${url}cookie-consent`, JSON.stringify({global_token, level: preferences.acceptedCategories})); 532 set_cookie('cookie_consent_logged', '1', 182, "\/"); 533 534 }, 535 536 guiOptions: { 537 consentModal: { 538 layout: "bar", 539 position: "bottom center",
540 flipButtons: false 541 }, 542 preferencesModal: { 543 layout: 'box', 544 } 545 }, 546 }); 547 }); 548 </script>
548 549
549<script> 550 'use strict'; 551 552 /* ------------------------------ 553 DOM Elements & Data Storage 554 ------------------------------ */ 555 const spotlight_wrapper = document.getElementById('spotlight_wrapper'); 556 const spotlight_modal = document.querySelector('.spotlight-modal'); 557 const spotlight_results = document.querySelector('#spotlight_results'); 558 let spotlight_results_array = []; 559 560 /* ------------------------------ 561 Show / Hide Spotlight 562 ------------------------------ */ 563 const spotlight_display = () => { 564 spotlight_wrapper.classList.remove('d-none'); 565 requestAnimationFrame(() => { 566 spotlight_wrapper.classList.add('show'); 567 }); 568 spotlight_wrapper.setAttribute('aria-hidden', 'false'); 569 document.querySelector('#spotlight_search').focus(); 570 }; 571 572 const spotlight_hide = () => { 573 spotlight_wrapper.classList.remove('show'); 574 spotlight_wrapper.setAttribute('aria-hidden', 'true'); 575 576 setTimeout(() => { 577 spotlight_wrapper.classList.add('d-none'); 578 }, 150); 579 }; 580 581 /* ------------------------------ 582 Fetch Pages & Store Locally 583 ------------------------------ */ 584 const spotlight_get_pages = async () => { 585 const form = new FormData(document.querySelector('#spotlight_form')); 586 const params = new URLSearchParams(form).toString(); 587 588 const response = await fetch(`${url}spotlight?global_token=${global_token}`, { method: 'get' }); 589 let data; 590 591 try { 592 data = await response.json(); 593 } catch (error) { 594 return false; 595 } 596 597 if(!response.ok || data.status === 'error') { 598 return false; 599 } else { 600 let results = data.details.map(obj => ({ ...obj, clicks: 0 })); 601 localStorage.setItem('3a3cbccce6752a0bb3bf80de8a88fca0_spotlight_results', JSON.stringify(results)); 602 } 603 604 return data.details; 605 }; 606 607 /* ------------------------------ 608 Build & Insert All Results Once 609 ------------------------------ */ 610 const build_all_spotlight_results = (pages) => { 611 // Sort them once by clicks (descending) 612 pages.sort((a, b) => b.clicks - a.clicks); 613 614 // Build in one shot 615 let html = ''; 616 for (const page of pages) { 617 // Include lowercase name/url as data attrs for quick toggling 618 html += ` 619 <a 620 href="${url}${page.url || ''}" 621 target="_blank" 622 class="my-3 p-3 bg-gray-50 rounded-2x position-relative text-decoration-none text-reset" 623 style="display: block" 624 data-spotlight-result-url="${page.url}" 625 data-spotlight-result-name="${page.name}" 626 > 627 <div class="d-flex justify-content-between align-items-center"> 628 <div> 629 <span>${page.name}</span> 630 <div class="small text-muted">${page.url ? '/' + page.url : url}</div> 631 </div> 632 <div> 633 <i class="fas fa-fw fa-lg fa-arrow-right text-muted"></i> 634 </div> 635 </div> 636 </a> 637 `; 638 } 639 640 spotlight_results.innerHTML = html; 641 642 document.querySelector('#spotlight_no_data').style.display = pages.length ? 'none' : 'block'; 643 }; 644 645 /* ------------------------------ 646 Toggle Display Instead of Re-rendering 647 ------------------------------ */ 648 const filter_spotlight_results = (search_value) => { 649 const spotlight_no_data = document.querySelector('#spotlight_no_data'); 650 const lower_search = search_value.toLowerCase(); 651 const links = spotlight_results.querySelectorAll('a[data-spotlight-result-url]'); 652 let matches = 0; 653 654 links.forEach(link => { 655 const page_name = link.getAttribute('data-spotlight-result-name').toLowerCase(); 656 const page_url = link.getAttribute('data-spotlight-result-url').toLowerCase(); 657 658 if(page_name.includes(lower_search) || page_url.includes(lower_search)) { 659 link.style.display = 'block'; 660 matches++; 661 } else { 662 link.style.display = 'none'; 663 } 664 }); 665 666 // If no matches, show #spotlight_no_data 667 spotlight_no_data.style.display = matches ? 'none' : 'block'; 668 }; 669 670 /* ------------------------------ 671 Initial Load 672 ------------------------------ */ 673 const spotlight_init = async () => { 674 675 // Show spinner only once, on load 676 spotlight_results.innerHTML = ` 677 <div class="my-3 p-3 bg-gray-50 rounded-2x position-relative d-flex justify-content-center"> 678 <div class="spinner-border spinner-border-lg" role="status"></div> 679 </div> 680 `; 681 682 // If no local results, fetch from server 683 if(!get_cookie('spotlight_has_results')) { 684 localStorage.removeItem('3a3cbccce6752a0bb3bf80de8a88fca0_spotlight_results'); 685 } 686 if(!localStorage.getItem('3a3cbccce6752a0bb3bf80de8a88fca0_spotlight_results')) { 687 const fetched_pages = await spotlight_get_pages(); 688 spotlight_results_array = fetched_pages || []; 689 } else { 690 spotlight_results_array = JSON.parse(localStorage.getItem('3a3cbccce6752a0bb3bf80de8a88fca0_spotlight_results')); 691 } 692 693 set_cookie('spotlight_has_results', 1, 90, "\/"); 694 695 // Now build the entire set 696 build_all_spotlight_results(spotlight_results_array); 697 698 // Optional: highlight first result if you want 699 const first_link = spotlight_results.querySelector('a'); 700 if(first_link) { 701 first_link.dispatchEvent(new Event('mouseover', { bubbles: true })); 702 } 703 }; 704 705 /* ------------------------------ 706 Debounced Search on Input 707 ------------------------------ */ 708 let search_timeout; 709 const spotlight_process_search = () => { 710 if(search_timeout) clearTimeout(search_timeout); 711 search_timeout = setTimeout(() => { 712 const search = document.querySelector('#spotlight_search').value; 713 714 filter_spotlight_results(search); 715 }, 100); 716 }; 717 718 /* ------------------------------ 719 Track Clicks via Delegation 720 ------------------------------ */ 721 spotlight_results.addEventListener('click', event => { 722 const link = event.target.closest('a[data-spotlight-result-url]'); 723 if(!link) return; 724 725 const result_url = link.getAttribute('data-spotlight-result-url'); 726 const page_obj = spotlight_results_array.find(p => p.url === result_url); 727 728 if(page_obj) { 729 page_obj.clicks += 1; 730 localStorage.setItem('3a3cbccce6752a0bb3bf80de8a88fca0_spotlight_results', JSON.stringify(spotlight_results_array)); 731 } 732 }); 733 734 /* ------------------------------ 735 Keyboard Navigation 736 ------------------------------ */ 737 const navigate_results = direction => { 738 // Only get visible links 739 const focusable_results = Array 740 .from(spotlight_results.querySelectorAll('a')) 741 .filter(a => a.style.display !== 'none'); 742 743 if(!focusable_results.length) return; 744 745 // Where is the current focus? 746 let current_index = focusable_results.indexOf(document.activeElement); 747 748 // If nothing is focused yet, treat it as -1 749 if(current_index === -1) current_index = -1; 750 751 // Move up or down among only visible items 752 if(direction === 'down') { 753 current_index = (current_index + 1) % focusable_results.length; 754 } else if(direction === 'up') { 755 current_index = (current_index - 1 + focusable_results.length) % focusable_results.length; 756 } 757 758 focusable_results[current_index].focus(); 759 }; 760 761 /* ------------------------------ 762 Global Keydown for CTRL+K, etc. 763 ------------------------------ */ 764 document.addEventListener('keydown', event => { 765 if((event.ctrlKey || event.metaKey) && event.key === 'k') { 766 event.preventDefault(); 767 spotlight_wrapper.getAttribute('aria-hidden') === 'true' ? spotlight_display() : spotlight_hide(); 768 } 769 770 if(spotlight_wrapper.getAttribute('aria-hidden') === 'false') { 771 if(event.key === 'Escape') { 772 spotlight_hide(); 773 } else if(event.key === 'ArrowDown') { 774 event.preventDefault(); 775 navigate_results('down'); 776 } else if(event.key === 'ArrowUp') { 777 event.preventDefault(); 778 navigate_results('up'); 779 } else if(event.key === 'Enter') { 780 /* handle enter if needed */ 781 } else { 782 document.querySelector('#spotlight_search').focus(); 783 } 784 } 785 }); 786 787 /* ------------------------------ 788 Hide on Click Outside 789 ------------------------------ */ 790 spotlight_wrapper.addEventListener('click', event => { 791 if(!spotlight_wrapper.classList.contains('d-none') && !spotlight_modal.contains(event.target)) { 792 spotlight_hide(); 793 } 794 }); 795 796 /* ------------------------------ 797 Attach Debounced Search 798 ------------------------------ */ 799 ['change','paste','keyup'].forEach(event_type => { 800 document.querySelector('#spotlight_search').addEventListener(event_type, spotlight_process_search); 801 }); 802 803 /* ------------------------------ 804 Submit Form -> Go to First Result 805 ------------------------------ */ 806 document.querySelector('#spotlight_form').addEventListener('submit', event => { 807 event.preventDefault(); 808 809 const first_visible = Array 810 .from(document.querySelectorAll('#spotlight_results a')) 811 .find(a => a.style.display !== 'none'); 812 813 if(first_visible) { 814 first_visible.click(); 815 } 816 }); 817 818 /* ------------------------------ 819 Kick off initial load 820 ------------------------------ */ 821 (async () => { 822 await spotlight_init(); 823 })(); 824 </script>
824 825 <style> 826 /* Spotlight search */ 827 .spotlight-wrapper { 828 background: hsla(0, 100%, 100%, 0.5); 829 position: fixed; 830 width: 100%; 831 height: 100%; 832 z-index: 200; 833 display: flex; 834 justify-content: center; 835 align-items: center; 836 opacity: 0; 837 transition: opacity .15s; 838 pointer-events: none; 839 } 840 841 [data-theme-style="dark"] .spotlight-wrapper { 842 background: hsla(0, 100%, 0%, 0.5); 843 } 844 845 .spotlight-wrapper.show { 846 opacity: 1; 847 pointer-events: auto; 848 } 849 850 .spotlight-modal { 851 padding: 2rem; 852 border-radius: calc(2*var(--border-radius)); 853 background: var(--gray-100); 854 } 855 856 .spotlight-results { 857 overflow-y: scroll; 858 max-height: 29rem; 859 } 860 861 .spotlight-results a { 862 border-radius: calc(2*var(--border-radius)); 863 } 864 865 .spotlight-results a:focus-visible { 866 outline: none; 867 } 868 </style> 869
869<script type="module" src="https://static.cloudflareinsights.com/beacon.min.js/v31edd6df95cf4e85bb4c19e7a9bdbcba1788362987495" integrity="sha512-iIg7k2xntmwu6/uSb5tpc/hySgZc4eoL31yB29W6tJFo2akwjPWcEqnCEdJvGexCL0KEQwVYv5BlowfhVz26hg==" data-cf-beacon='{"version":"2024.11.0","token":"457941b1852a4cd196b54f9347408e4d","r":1,"spa":2}' crossorigin="anonymous"></script>
869 870</body> 871</html>
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.