1function fupi_top_helpers(){ 2 3 'use strict'; 4 5 var d = document; 6 7 // VARS 8 9 FP.v = {}; 10 fp.track_queue = []; 11 fpdata.activity = { total : 0, last : 0, current : 0 }; 12 fpdata.refreshed = false; 13 14 if ( document.referrer == document.location.origin + document.location.pathname ) { 15 fpdata.refreshed = true; 16 } else { 17 if ( performance.navigation ? performance.navigation.type === performance.navigation.TYPE_RELOAD : performance.getEntriesByType('navigation')[0].type === 'reload' ) fpdata.refreshed = true; // deprecated method first, the new one later 18 } 19 20 // HELPERS 21 22 function getFormattedDateTime(){ 23 const d = new Date(); 24 25 const year = d.getFullYear(); 26 const month = d.getMonth() + 1; 27 const day = d.getDate(); 28 const hours = d.getHours() * 100; 29 const minutes = d.getMinutes(); 30 31 return { 32 year: year, 33 month: month, 34 day: day, 35 time: hours + minutes 36 }; 37 } 38 39 fpdata.date = getFormattedDateTime(); 40 41 function check_if_can_save_wpfp_cookies( first_check = false ) { 42 43 // save previous state 44 let prev_check = !! fp.vars.can_save_wpfp_cookies; // "!!" changes undefined into false 45 46 // get current state 47 fp.vars.can_save_wpfp_cookies = ! fp.notice.enabled || fp.notice.mode == 'notify' || fp.notice.mode == 'hide' || ( fp.notice.mode == 'optout' && ! fpdata.cookies ) || ( fp.notice.mode == 'optin' && fpdata.cookies && fpdata.cookies.stats ); 48 49 // check if the state has changed 50 fp.vars.consents_changed = first_check ? false : prev_check != fp.vars.can_save_wpfp_cookies; 51 } 52 53 function shouldCustomScriptLoadHere( geo ){ 54 55 let geo_method = geo[0], 56 geo_countries = geo[1]; 57 58 if ( fp.main.geo && geo_method && geo_countries ) { // we check fp.geo to prevent situations when user disabled geo but didn't save new tools settings 59 60 if ( fp.ready ) { 61 return geo_method == 'incl' ? geo_countries.includes( fpdata.country ) : ! geo_countries.includes( fpdata.country ); 62 } 63 return false; 64 } 65 66 return true; 67 } 68 69 function shouldScriptLoadHere( id ){ 70 71 if ( fp.main.geo && fp[id].limit_country ) { // we check fp.main.geo to prevent situations when user disabled geo but didn't save new tools settings 72 73 if ( fp.ready ) { 74 75 if ( fp[id].limit_country.method == 'excl' ) { 76 return ! fp[id].limit_country.countries.includes( fpdata.country ); 77 } else { 78 return fp[id].limit_country.countries.includes( fpdata.country ); 79 } 80 } 81 82 return false; 83 } 84 85 return true; 86 }; 87 88 function get_session_data_from_cookies(){ 89 90 let session_cookie = FP.readCookie('fp_current_session'); 91 if ( session_cookie ) fpdata.current_session = JSON.parse(session_cookie); 92 93 /* <fs_premium_only> */ 94 if ( fp.main.is_pro ) { 95 let recent_sessions_cookie = FP.readCookie('fp_recent_sessions'); 96 if ( recent_sessions_cookie ) fpdata.recent_sessions = JSON.parse(recent_sessions_cookie); 97 } 98 /* </fs_premium_only> */ 99 } 100 101 // 102 // FP - start 103 // 104 105 FP.setCookie = (name, value, days = 0, mins = 0, path = "/") => { 106 var expires = ""; 107 if ( days > 0 || mins > 0 ) { 108 var date = new Date(); 109 if (days > 0) { 110 date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000); 111 } else { 112 date.setTime(date.getTime() + mins * 60 * 1000); 113 } 114 expires = "; expires=" + date.toGMTString(); 115 }; 116 d.cookie = name + "=" + value + expires + "; path=" + path + "; sameSite=strict"; 117 }; 118 119 FP.deleteCookie = name => { FP.setCookie(name, "", -1); }; 120 121 FP.getUrlParamByName = ( name, url = false ) => { 122 if ( ! url ) { 123 url = window.location.search; 124 } else { 125 url = url.split('?')[1]; 126 if ( ! url ) return null; 127 }; 128 129 const queryString = url,
130 urlParams = new URLSearchParams(queryString); 131 return urlParams.get(name); 132 }; 133 134 FP.nl2Arr = nl => nl ? [].slice.call(nl) : false; 135 136 FP.findID = (e, c) => { 137 if ( c === null ) return null; 138 if ( !e ) return false; 139 c = c || document; 140 return c.getElementById(e); 141 }; 142 143 FP.findFirst = (e, c) => { 144 if ( c === null ) return null; 145 if ( !e ) return false; 146 c = c || document; 147 return c.querySelector(e); 148 }; 149 150 FP.findAll = (e, c) => { 151 if ( c === null ) return []; 152 if ( ! e ) return false; 153 c = c || document; 154 return FP.nl2Arr(c.querySelectorAll(e)); 155 }; 156 157 FP.getScript = ( url, cb, attrs, tag = 'script', fallback = false ) => { 158 159 attrs = attrs || false; 160 var new_tag = ""; 161 162 if ( tag == "img" ) { 163 new_tag = d.createElement('img'); 164 new_tag.src = url; 165 } else if ( tag == "link" ) { 166 new_tag = d.createElement('link'); 167 new_tag.href = url; 168 } else { 169 new_tag = d.createElement('script') 170 new_tag.src = url; 171 new_tag.type = 'application/javascript'; 172 } 173 174 if ( cb ) new_tag.onload = cb; 175 176 if ( fallback ) new_tag.onerror = ()=>{ FP.getScript( fallback, cb, attrs, tag ); }; 177 178 if ( attrs ) { 179 // check if attrs holds a reference to and HTML tag 180 if ( attrs instanceof Element ) { 181 let old_tag = attrs; 182 // copy from the original tag (with exceptions) 183 Array.from( old_tag.attributes ).forEach( attr => { 184 if ( attr.name !== 'type' && attr.name !== 'data-src' && ! attr.name.includes('fupi') ) { 185 new_tag.setAttribute( attr.name, attr.value ); 186 } 187 }); 188 // or add provided values 189 } else { 190 for (var key in attrs) { 191 if ( key !== "/" ) new_tag.setAttribute(key, attrs[key]); 192 } 193 } 194 } 195 196 d.getElementsByTagName("head")[0].appendChild(new_tag); 197 }; 198 199 FP.createTag = FP.getScript; 200 201 function loadInlineScript(temp_script) { 202 203 let scr_id = temp_script.dataset?.fupi_id, 204 orig_id = scr_id.replace('fp_',''), 205 is_cscr = temp_script.dataset?.module == 'cscr'; 206 207 if ( ! scr_id ) return; 208 209 let new_script = document.createElement('script'); 210 211 new_script.innerHTML = temp_script.innerHTML; 212 temp_script.parentNode.replaceChild(new_script, temp_script); 213 214 if ( fp.main.debug ) { 215 if ( is_cscr && fp.cscr[orig_id] ) { 216 console.log( "[FP] Custom script loaded: " + fp.cscr[orig_id] ); 217 } else { 218 console.log( "[FP] Inline script loaded"); 219 } 220 }; 221 222 fp.loaded.push( orig_id ); 223 }; 224 225 FP.sendEvt = (evt_name, details_a) => { 226 var details = details_a ? { 'detail' : details_a } : {}, 227 fp_event = new CustomEvent( evt_name, details ); 228 document.dispatchEvent(fp_event); 229 }; 230 231 FP.getRandomStr = ()=>{ 232 return ( Math.random() + 1 ).toString(36).substring(2); 233 }; 234 235 FP.updateConsents = () => { 236 237 if ( fp.vars.use_other_cmp ) return; 238 239 if ( ! fp.main.track_current_user ) { 240 241 if ( fp.main.debug ) console.log("[FP] Current user cannot be tracked"); 242 243 // if the user made a choice in the past 244 } else if ( fpdata.cookies ){ 245 246 set_consents_in_fpdata( fpdata?.cookies?.stats, fpdata?.cookies?.personalisation, fpdata?.cookies?.marketing ); 247 248 // if no choice was made in the past 249 } else { 250 251 // deny all if consent banner is in optin mode 252 if ( fp.notice.enabled && fp.notice.mode == "optin" ) { 253 254 set_consents_in_fpdata(); 255 256 // agree to all if consent banner is disabled or we are in optout or notification mode 257 } else { 258 set_consents_in_fpdata(true, true, true); 259 } 260 } 261 262 if ( ! fp.main.is_customizer ) { 263 264 // set MS Ads consent 265 266 if ( fp.main.track_current_user && fpdata.cookies ){ 267 if ( fpdata.cookies.stats && fpdata.cookies.marketing ) { 268 window.uetq.push( "consent", "update", { 269 "ad_storage": "granted" 270 });
271 } 272 } else { 273 if ( ! ( fp.notice.enabled && fp.notice.mode == "optin" ) ) { 274 window.uetq.push( "consent", "update", { 275 "ad_storage": "granted" 276 }); 277 } 278 } 279 280 // Set GTAG consents 281 282 ["gtag", "fupi_gtm_gtag"].forEach( tag_name => { 283 284 if ( tag_name == "fupi_gtm_gtag" && ! window.fupi_gtm_gtag ) return; 285 286 // update if the user made a choice in the past 287 if ( fp.main.track_current_user && fpdata.cookies ){ 288 289 FP.set_gtag_consents( tag_name, "update", fpdata?.cookies?.stats, fpdata?.cookies?.personalisation, fpdata?.cookies?.marketing ); 290 if ( fp.main.debug ) console.log("[FP] Google consents set to user choices"); 291 292 // if no choice was made in the past 293 } else { 294 295 // agree to all if consent banner is disabled or is in optout or notification mode 296 if ( ! ( fp.notice.enabled && fp.notice.mode == "optin" ) ) { 297 298 FP.set_gtag_consents( tag_name, "update", true, true, true ); 299 if ( fp.main.debug ) console.log("[FP] All Google consents granted"); 300 301 }; 302 } 303 } ); 304 } 305 } 306 307 FP.postToServer = ( event_data_a, cb = false ) => { 308 309 if ( fpdata.is_robot ) return; 310 if ( fp.main.debug ) console.log( "[FP] Posting to server", event_data_a ); 311 312 let fetch_url = fp.main.server_method == "rest" ? "/index.php?rest_route=/fupi/v1/sender" : "/wp-admin/admin-ajax.php?action=fupi_ajax"; 313 314 if ( fp.main.debug || event_data_a[0][0] == 'cdb') { 315 316 fetch( fetch_url, { 317 method: "POST", 318 body: JSON.stringify( event_data_a ), 319 credentials: 'same-origin', 320 headers: { 321 "Content-type": "application/json; charset=UTF-8", 322 // "X-WP-Nonce": fp_nonce 323 } 324 }) 325 .then((response) => response.json()) 326 .then((json) => { 327 if ( cb ) { 328 cb(json); 329 } else { 330 console.log( "[FP] Server response", json); 331 } 332 }); 333 334 } else { 335 336 fetch( fetch_url, { 337 method: "POST", 338 credentials: 'same-origin', 339 body: JSON.stringify( event_data_a ), 340 headers: { 341 "Content-type": "application/json; charset=UTF-8", 342 // "X-WP-Nonce": fp_nonce 343 } 344 }); 345 } 346 }; 347 348 // fires function every X ms with an option to fire them ADDITIONALLY on start ("leading") and after events ("trailing") 349 FP.throttle = function (func, wait, options) { 350 var context, args, result; 351 var timeout = null; 352 var previous = 0; 353 if (!options) options = {}; 354 355 var later = function later() { 356 previous = options.leading === false ? 0 : Date.now(); 357 timeout = null; 358 result = func.apply(context, args); 359 if (!timeout) context = args = null; 360 }; 361 362 return function () { 363 var now = Date.now(); 364 if (!previous && options.leading === false) previous = now; 365 var remaining = wait - (now - previous); 366 context = this; 367 args = arguments; 368 369 if (remaining <= 0 || remaining > wait) { 370 if (timeout) { 371 clearTimeout(timeout); 372 timeout = null; 373 } 374 375 previous = now; 376 result = func.apply(context, args); 377 if (!timeout) context = args = null; 378 } else if (!timeout && options.trailing !== false) { 379 timeout = setTimeout(later, remaining); 380 } 381 382 return result; 383 }; 384 }; 385 386 FP.remove = el => { if (el) el.parentNode.removeChild(el); }; 387 388 FP.addAction = function( action_name, fn ){ 389 390 let arr = Array.isArray(action_name) ? action_name : [action_name]; // make sure that trigger is in an array 391 392 arr.forEach(function ( name , i) { 393 if ( ! fp.actions[name] ) fp.actions[name] = []; 394 fp.actions[name].push( fn ); 395 }); 396 } 397 398 FP.doActions = ( action_name, args_o = null, cb ) => { 399 if ( fp.actions[action_name] ) fp.actions[action_name].forEach( fn => { 400 let return_val = fn( args_o ); 401 if ( typeof return_val !== 'undefined' ) args_o = return_val; 402 } ); 403 if ( cb ) cb( args_o ); 404 } 405 406 FP.hasActions = action_name => { 407 return fp.actions[action_name] && fp.actions[action_name].length > 0;
408 }; 409 410 FP.isScriptAllowedToLoad = function( id, force_load, permissions_a, geo_a ){ 411 412 // STOP if we don't have all the basic data yet 413 if ( ! fp.ready ) return false; 414 415 // STOP if the script has already loaded 416 if ( fp.loaded.includes(id) ) return false; 417 418 // START if the load is forced 419 if ( force_load ) return true; 420 421 // STOP if the tab is not in focus AND we are NOT on WooCommerce checkout page 422 if ( fpdata.page_type !== 'Woo Order Received' ) { 423 if ( document.hidden ) return false; 424 } 425 426 // STOP tracking an excluded visitor (MUST be after checking FORCE LOAD) 427 if ( ! fp.main.track_current_user ) return false; 428 429 // STOP if the script is set NOT to load in the current location 430 if ( geo_a && ! shouldCustomScriptLoadHere( geo_a ) ) return false; 431 432 // STOP if any permissions need to be given in this location... 433 if ( fp.notice.enabled && fp.notice.mode == 'optin' && ! fpdata.cookies && permissions_a.length > 0 ) return false; 434 435 // STOP if required permissions are not given 436 if ( fpdata.cookies && permissions_a.length > 0 ) { 437 if ( ! permissions_a.every( permission => fpdata.cookies[permission] ) ) return false; 438 } 439 440 return true; 441 }; 442 443 FP.isAllowedToLoad = function( module_id, permissions_a, required_a, nr, tool_does_not_use_cookies = false ) { 444 445 var id = nr ? module_id + nr : module_id; 446 447 // STOP if we don't have all the basic data yet 448 if ( ! fp.ready ) return false; 449 450 // STOP if we have no settings for this tool 451 if ( ! fp[id] ) return false; 452 453 // STOP if the script has already loaded 454 if ( fp.loaded.includes(id) ) return false; 455 456 // STOP if the required data is missing 457 if ( required_a.some( req => ! fp[id][req] ) ) return false; 458 459 // START if the load is forced 460 if ( fp[id].force_load ) return true; 461 462 // STOP if the tab is not in focus AND we are NOT on WooCommerce checkout page 463 if ( fpdata.page_type !== 'Woo Order Received' ) { 464 if ( document.hidden ) return false; 465 } 466 467 // STOP tracking an excluded visitor (MUST be after checking FORCE LOAD) 468 if ( ! fp.main.track_current_user ) return false; 469 470 // STOP if the script is set NOT to load in the current location 471 if ( ! shouldScriptLoadHere( id ) ) return false; 472 473 // START 474 // if the tool doesn't use cookies 475 if ( tool_does_not_use_cookies ) return true; 476 477 // STOP if we wait for consent but some permissions need to be given 478 if ( fp.notice.enabled && fp.notice.mode == 'optin' && ! fpdata.cookies && permissions_a.length > 0) return false; 479 480 // STOP if user chose their cookie preferences but some required permissions are missing 481 if ( fp.notice.enabled && fpdata.cookies && permissions_a.length > 0 ) { 482 if ( ! permissions_a.every( permission => fpdata.cookies[permission] ) ) return false; 483 } 484 485 return true; 486 }; 487 488 FP.startActivityTimer = function () { 489 490 fpdata.activity.last = 0; 491 492 if (!FP.v.activityTimerRunning) { 493 FP.v.activityTimerRunning = true; 494 FP.v.activityTimer = setInterval(function () { 495 496 fpdata.activity.total++; 497 fpdata.activity.current++; 498 fpdata.activity.last++; 499 500 FP.doActions( 'active_time_tick' ); 501 502 if ( fpdata.activity.last >= 15 ) FP.stopActivityTimer(); // stop timer after 15 secs from last activity 503 }, 1000); 504 } 505 }; 506 507 FP.stopActivityTimer = function () { 508 if (FP.v.activityTimerRunning) { 509 FP.v.activityTimerRunning = false; 510 clearInterval(FP.v.activityTimer); 511 } 512 }; 513 514 FP.encode = function (string) { 515 return window.btoa(string).split('=').join('') 516 } 517 518 FP.detectAddedElement = callback => { 519 520 const observer = new MutationObserver( mutations => { 521 mutations.forEach( mutation => { 522 if ( mutation.type === 'childList' ) { 523 callback( mutation.addedNodes ); 524 } 525 } ); 526 } ); 527 528 observer.observe( document.body, { 529 childList: true, 530 subtree: true 531 } ); 532 } 533 534 FP.initCondTracking = ( events_settings, cb ) => { 535 536 if ( ! ( events_settings && fp.atrig ) ) return; 537 if ( ! fp.atrig.actions ) fp.atrig.actions = {}; 538
539 events_settings.forEach( e => { 540 541 if ( ! fp.atrig.actions[e.atrig_id] ) fp.atrig.actions[e.atrig_id] = []; 542 543 fp.atrig.actions[e.atrig_id].push( { 544 'func' : cb.bind( this, e ), 545 'repeat' : e.repeat 546 } ); 547 }); 548 } 549 550 FP.updateSessionData = () => { 551 552 check_if_can_save_wpfp_cookies(); 553 554 if ( fp.vars.consents_changed ) { 555 556 // if we can no longer use session cookies 557 if ( ! fp.vars.can_save_wpfp_cookies ) { 558 559 // delete everything 560 FP.deleteCookie( 'fp_current_session' ); 561 delete fpdata.current_session; 562 /* <fs_premium_only> */ 563 if ( fp.main.is_pro ) { 564 FP.deleteCookie( 'fp_recent_sessions' ); 565 delete fpdata.recent_sessions; 566 } 567 /* </fs_premium_only> */ 568 569 // if we can now use session cookies 570 } else { 571 572 // get latest sesion data (in case user agreed to cookies on a different tab) 573 get_session_data_from_cookies(); 574 575 // set new data if it wasn't set before (when a user has just chosen sth in the banner) 576 ! fpdata.current_session ? create_new_single_session_data() : update_single_session_data(); 577 /* <fs_premium_only> */ 578 if ( fp.main.is_pro ) { 579 ! fpdata.recent_sessions ? create_new_recent_sessions_data() : update_recent_sessions_data(); 580 } 581 /* </fs_premium_only> */ 582 }; 583 584 } else { 585 // get latest sesion data (in case user visited a different tab before opening this one) 586 get_session_data_from_cookies(); 587 } 588 } 589 590 FP.isClickTarget = function( selector ){ 591 return ( ! fpdata.clicked.link && ! fpdata.clicked.middle && fpdata.clicked.element.matches( selector ) ) || ( fpdata.clicked.link && fpdata.clicked.link.element.matches( selector ) ); 592 } 593 594 /* <fs_premium_only> */ 595 596 FP.changeReferrer = ref => { 597 598 if ( ref == 'non_http' ) { 599 600 let rules = JSON.parse( fp.track.track_non_http ); 601 602 for ( const nr in rules ) { 603 604 let match_found = false; 605 606 if ( rules[nr].compare == "incl" ) { 607 match_found = document.referrer.includes(rules[nr].search); 608 } else if ( rules[nr].compare == "start" ){ 609 match_found = document.referrer.indexOf(rules[nr].search) == 0; 610 } else { 611 match_found = rules[nr].search == document.referrer; 612 }; 613 614 if ( match_found ) { 615 ref = rules[nr].replace.indexOf('http') == 0 ? rules[nr].replace : "https://" + rules[nr].replace; 616 ref = ref.slice(-1) == "/" ? ref : ref + "/"; 617 delete window.document.referrer; 618 window.document.__defineGetter__('referrer', ()=>{return ref;}); 619 break; 620 } 621 } 622 623 } else if ( ref == 'switch_ref' ) { 624 625 let rules = JSON.parse( fp.track.switch_ref ); 626 627 for ( const nr in rules ) { 628 if ( document.location.href.includes( rules[nr].search ) ) { 629 delete window.document.referrer; 630 window.document.__defineGetter__('referrer', ()=>{return rules[nr].replace;}); 631 break; 632 }; 633 } 634 635 } else { 636 delete window.document.referrer; 637 window.document.__defineGetter__('referrer', ()=>{return ref;}); 638 } 639 }; 640 641 /* </fs_premium_only> */ 642 643 // 644 // 645 // FP - END 646 // 647 // 648 649 // BROKEN LINK TRACKING + REDIRECT TO A CUSTOM 404 PAGE 650 if ( fp.track.track404 && fpdata.page_type == "404" && ! FP.getUrlParamByName("broken_link_location") ){ 651 const location = fp.track.redirect404_url ? new URL( fp.track.redirect404_url ) : window.location; 652 window.location = location + ( location.search ? "&" : "?" ) + "broken_link_location=" + ( document.referrer || "direct_traffic_or_unknown" ) + "&broken_link=" + window.location; 653 } 654 655 // Random number (sometimes gets handy) 656 fp.random = FP.getRandomStr(7); 657 658 // CHECK FOR BOT TRAFFIC 659 // -- modified version of https://stackoverflow.com/a/65563155/7702522 660 661 fpdata.is_robot = (() => { 662 663 // SMALL list 664 if ( fp.main.bot_list == "basic" ) { 665 666 const robots = new RegExp([/bot/,/spider/,/crawl/,/APIs-Google/,/AdsBot/,/Googlebot/,/mediapartners/,/Google Favicon/,/FeedFetcher/,/Google-Read-Aloud/,/googleweblight/,/bingbot/,/yandex/,/baidu/,/duckduck/,/Yahoo Link Preview/,/ia_archiver/,/facebookexternalhit/,/pinterest\.combot/,/redditbot/,/slackbot/,/Twitterbot/,/WhatsApp/,/S[eE][mM]rushBot/].map((r) => r.source).join("|"),"i"); 667 668 return robots.test(navigator.userAgent); 669 670 // BIG list 671 } else if ( fp.main.bot_list == "big" ) { 672 673 const robots = new RegExp([ 674 /Googlebot/, /AdsBot/, /Feedfetcher-Google/, /Mediapartners-Google/, /Mediapartners/, /APIs-Google/, 675 /Google-InspectionTool/, /Storebot-Google/, /GoogleOther/, /bingbot/, /Slurp/, /wget/, /LinkedInBot/, 676 /Python-urllib/, /python-requests/, /aiohttp/, /httpx/, /libwww-perl/, /httpunit/, /Nutch/, 677 /Go-http-client/, /phpcrawl/, /msnbot/, /jyxobot/, /FAST-WebCrawler/, /FAST Enterprise Crawler/, 678 /BIGLOTRON/, /Teoma/, /convera/, /seekbot/, /Gigabot/, /Gigablast/, /exabot/, /ia_archiver/, 679 /GingerCrawler/, /webmon/, /HTTrack/, /grub\.org/, /UsineNouvelleCrawler/, /antibot/, 680 /netresearchserver/, /speedy/, /fluffy/, /findlink/, /msrbot/, /panscient/, /yacybot/, /AISearchBot/, 681 /ips-agent/, /tagoobot/, /MJ12bot/, /woriobot/, /yanga/, /buzzbot/, /mlbot/, /yandex\.combots/, 682 /purebot/, /Linguee Bot/, /CyberPatrol/, /voilabot/, /Baiduspider/, /citeseerxbot/, /spbot/, 683 /twengabot/, /postrank/, /Turnitin/, /scribdbot/, /page2rss/, /sitebot/, /linkdex/, /Adidxbot/, 684 /ezooms/, /dotbot/, /Mail\.RU_Bot/, /discobot/, /heritrix/, /findthatfile/, /europarchive\.org/, 685 /NerdByNature\.Bot/, /sistrix crawler/, /Ahrefs/, /fuelbot/, /CrunchBot/, /IndeedBot/, 686 /mappydata/, /woobot/, /ZoominfoBot/, /PrivacyAwareBot/, /Multiviewbot/, /SWIMGBot/, /Grobbot/, 687 /eright/, /Apercite/, /semanticbot/, /Aboundex/, /domaincrawler/, /wbsearchbot/, /summify/, /CCBot/, 688 /edisterbot/, /SeznamBot/, /ec2linkfinder/, /gslfbot/, /aiHitBot/, /intelium_bot/, 689 /facebookexternalhit/, /Yeti/, /RetrevoPageAnalyzer/, /lb-spider/, /Sogou/, /lssbot/, /careerbot/, 690 /wotbox/, /wocbot/, /ichiro/, /DuckDuckBot/, /lssrocketcrawler/, /drupact/, /webcompanycrawler/, 691 /acoonbot/, /openindexspider/, /gnam gnam spider/, /web-archive-net\.com\.bot/, /backlinkcrawler/, 692 /coccoc/, /integromedb/, /content crawler spider/, /toplistbot/, /it2media-domain-crawler/, 693 /ip-web-crawler\.com/, /siteexplorer\.info/, /elisabot/, /proximic/, /changedetection/, /arabot/, 694 /WeSEE:Search/, /niki-bot/, /CrystalSemanticsBot/, /rogerbot/, /360Spider/, /psbot/, 695 /InterfaxScanBot/, /CC Metadata Scaper/, /g00g1e\.net/, /GrapeshotCrawler/, /urlappendbot/, 696 /brainobot/, /fr-crawler/, /binlar/, /SimpleCrawler/, /Twitterbot/, /cXensebot/, /smtbot/, 697 /bnf\.fr_bot/, /A6-Indexer/, /ADmantX/, /Facebot/, /OrangeBot/, /memorybot/, /AdvBot/, 698 /MegaIndex/, /SemanticScholarBot/, /ltx71/, /nerdybot/, /xovibot/, /BUbiNG/, /Qwantify/, 699 /archive\.org_bot/, /Applebot/, /TweetmemeBot/, /crawler4j/, /findxbot/, /SemrushBot/, 700 /yoozBot/, /lipperhey/, /Y!J/, /Domain Re-Animator Bot/, /AddThis/, /Screaming Frog SEO Spider/, 701 /MetaURI/, /Scrapy/, /Livelapbot/, /OpenHoseBot/, /CapsuleChecker/, /collection@infegy\.com/,
702 /IstellaBot/, /DeuSu/, /betaBot/, /Cliqzbot/, /MojeekBot/, /netEstate NE Crawler/, 703 /SafeSearch microdata crawler/, /Gluten Free Crawler/, /Sonic/, /Sysomos/, /Trove/, /deadlinkchecker/, 704 /Slack-ImgProxy/, /Embedly/, /RankActiveLinkBot/, /iskanie/, /SafeDNSBot/, /SkypeUriPreview/, 705 /Veoozbot/, /Slackbot/, /redditbot/, /datagnionbot/, /Google-Adwords-Instant/, /adbeat_bot/, 706 /WhatsApp/, /contxbot/, /pinterest\.combot/, /electricmonk/, /GarlikCrawler/, /BingPreview/, 707 /vebidoobot/, /FemtosearchBot/, /Yahoo Link Preview/, /MetaJobBot/, /DomainStatsBot/, /mindUpBot/, 708 /Daum/, /Jugendschutzprogramm-Crawler/, /Xenu Link Sleuth/, /Pcore-HTTP/, /moatbot/, /KosmioBot/, 709 /pingdom/, /AppInsights/, /PhantomJS/, /Gowikibot/, /PiplBot/, /Discordbot/, /TelegramBot/, 710 /Jetslide/, /newsharecounts/, /James BOT/, /Barkrowler/, /TinEye/, /SocialRankIOBot/, 711 /trendictionbot/, /Ocarinabot/, /epicbot/, /Primalbot/, /DuckDuckGo-Favicons-Bot/, /GnowitNewsbot/, 712 /Leikibot/, /LinkArchiver/, /YaK/, /PaperLiBot/, /Digg Deeper/, /dcrawl/, /Snacktory/, /AndersPinkBot/, 713 /Fyrebot/, /EveryoneSocialBot/, /Mediatoolkitbot/, /Luminator-robots/, /ExtLinksBot/, /SurveyBot/, 714 /NING/, /okhttp/, /Nuzzel/, /omgili/, /PocketParser/, /YisouSpider/, /um-LN/, /ToutiaoSpider/, 715 /MuckRack/, /Jamie's Spider/, /AHC/, /NetcraftSurveyAgent/, /Laserlikebot/, /^Apache-HttpClient/, 716 /AppEngine-Google/, /Jetty/, /Upflow/, /Thinklab/, /Traackr\.com/, /Twurly/, /Mastodon/, /http_get/, 717 /DnyzBot/, /botify/, /007ac9 Crawler/, /BehloolBot/, /BrandVerity/, /check_http/, /BDCbot/, 718 /ZumBot/, /EZID/, /ICC-Crawler/, /ArchiveBot/, /^LCC /, /filterdb\.iss\.netcrawler/, /BLP_bbot/, 719 /BomboraBot/, /Buck/, /Companybook-Crawler/, /Genieo/, /magpie-crawler/, /MeltwaterNews/, 720 /Moreover/,/newspaper/,/ScoutJet/,/sentry/,/StorygizeBot/,/UptimeRobot/,/OutclicksBot/, 721 /seoscanners/,/Hatena/,/Google Web Preview/,/MauiBot/,/AlphaBot/,/SBL-BOT/,/IAS crawler/, 722 /adscanner/,/Netvibes/,/acapbot/,/Baidu-YunGuanCe/,/bitlybot/,/blogmuraBot/,/Bot\.AraTurka\.com/, 723 /bot-pge\.chlooe\.com/,/BoxcarBot/,/BTWebClient/,/ContextAd Bot/,/Digincore bot/,/Disqus/,/Feedly/, 724 /Fetch/,/Fever/,/Flamingo_SearchEngine/,/FlipboardProxy/,/g2reader-bot/,/G2 Web Services/,/imrbot/, 725 /K7MLWCBot/,/Kemvibot/,/Landau-Media-Spider/,/linkapediabot/,/vkShare/,/Siteimprove\.com/,/BLEXBot/, 726 /DareBoost/,/ZuperlistBot/,/Miniflux/,/Feedspot/,/Diffbot/,/SEOkicks/,/tracemyfile/,/Nimbostratus-Bot/, 727 /zgrab/,/PR-CY\.RU/,/AdsTxtCrawler/,/Datafeedwatch/,/Zabbix/,/TangibleeBot/,/google-xrawler/,/axios/, 728 /Amazon CloudFront/,/Pulsepoint/,/CloudFlare-AlwaysOnline/,/Google-Structured-Data-Testing-Tool/, 729 /WordupInfoSearch/,/WebDataStats/,/HttpUrlConnection/,/Seekport Crawler/,/ZoomBot/,/VelenPublicWebCrawler/, 730 /MoodleBot/,/jpg-newsbot/,/outbrain/,/W3C_Validator/,/Validator\.nu/,/W3C-checklink/,/W3C-mobileOK/, 731 /W3C_I18n-Checker/,/FeedValidator/,/W3C_CSS_Validator/,/W3C_Unicorn/,/Google-PhysicalWeb/,/Blackboard/, 732 /ICBot/,/BazQux/,/Twingly/,/Rivva/,/Experibot/,/awesomecrawler/,/Dataprovider\.com/,/GroupHigh/, 733 /theoldreader\.com/,/AnyEvent/,/Uptimebot\.org/,/Nmap Scripting Engine/,/2ip\.ru/,/Clickagy/, 734 /Caliperbot/,/MBCrawler/,/online-webceo-bot/,/B2B Bot/,/AddSearchBot/,/Google Favicon/,/HubSpot/, 735 /Chrome-Lighthouse/,/HeadlessChrome/,/CheckMarkNetwork/,/www\.uptime\.com/,/Streamline3Bot/,/serpstatbot/, 736 /MixnodeCache/,/^curl/,/SimpleScraper/,/RSSingBot/,/Jooblebot/,/fedoraplanet/,/Friendica/,/NextCloud/, 737 /Tiny Tiny RSS/,/RegionStuttgartBot/,/Bytespider/,/Datanyze/,/Google-Site-Verification/,/TrendsmapResolver/, 738 /tweetedtimes/,/NTENTbot/,/Gwene/,/SimplePie/,/SearchAtlas/,/Superfeedr/,/feedbot/,/UT-Dorkbot/,/Amazonbot/, 739 /SerendeputyBot/,/Eyeotabot/,/officestorebot/,/Neticle Crawler/,/SurdotlyBot/,/LinkisBot/,/AwarioSmartBot/, 740 /AwarioRssBot/,/RyteBot/,/FreeWebMonitoring SiteChecker/,/AspiegelBot/,/NAVER Blog Rssbot/,/zenback bot/, 741 /SentiBot/,/Domains Project/,/Pandalytics/,/VKRobot/,/bidswitchbot/,/tigerbot/,/NIXStatsbot/,/Atom Feed Robot/, 742 /curebot/,/PagePeeker/,/Vigil/,/rssbot/,/startmebot/,/JobboerseBot/,/seewithkids/,/NINJA bot/,/Cutbot/, 743 /BublupBot/,/BrandONbot/,/RidderBot/,/Taboolabot/,/Dubbotbot/,/FindITAnswersbot/,/infoobot/,/Refindbot/, 744 /BlogTraffic\d\.\d+ Feed-Fetcher/,/SeobilityBot/,/Cincraw/,/Dragonbot/,/VoluumDSP-content-bot/,/FreshRSS/, 745 /BitBot/,/^PHP-Curl-Class/,/Google-Certificates-Bridge/,/centurybot/,/Viber/,/e\.ventures Investment Crawler/, 746 /evc-batch/,/PetalBot/,/virustotal/,/(^| )PTST/,/minicrawler/,/Cookiebot/,/trovitBot/,/seostar\.co/,/IonCrawl/, 747 /Uptime-Kuma/,/SeekportBot/,/FreshpingBot/,/Feedbin/,/CriteoBot/,/Snap URL Preview Service/,/Better Uptime Bot/, 748 /RuxitSynthetic/,/Google-Read-Aloud/,/ValveSteam/,/OdklBot/,/GPTBot/,/ChatGPT-User/,/YandexRenderResourcesBot/, 749 /LightspeedSystemsCrawler/,/ev-crawler/,/BitSightBot/,/woorankreview/,/Google-Safety/,/AwarioB
749ot/,/DataForSeoBot/, 750 /Linespider/,/WellKnownBot/,/A Patent Crawler/,/StractBot/,/search\.marginalia\.nu/,/YouBot/,/Nicecrawler/,/Neevabot/, 751 /BrightEdge Crawler/,/SiteCheckerBotCrawler/,/TombaPublicWebCrawler/,/CrawlyProjectCrawler/,/KomodiaBot/,/KStandBot/, 752 /CISPA Webcrawler/,/MTRobot/,/hyscore\.io/,/AlexandriaOrgBot/,/2ip bot/,/Yellowbrandprotectionbot/,/SEOlizer/, 753 /vuhuvBot/,/INETDEX-BOT/,/Synapse/,/t3versionsBot/,/deepnoc/,/Cocolyzebot/,/hypestat/,/ReverseEngineeringBot/, 754 /sempi\.tech/,/Iframely/,/MetaInspector/,/node-fetch/,/lkxscan/,/python-opengraph/,/OpenGraphCheck/, 755 /developers\.google\.com\+websnippet/,/SenutoBot/,/MaCoCu/,/NewsBlur/,/inoreader/,/NetSystemsResearch/,/PageThing/, 756 /WordPress/,/PhxBot/,/ImagesiftBot/,/Expanse/,/InternetMeasurement/,/^BW/,/GeedoBot/,/Audisto Crawler/, 757 /PerplexityBot/,/claudebot/,/Monsidobot/,/GroupMeBot/].map((r) => r.source).join("|"),"i"); 758 759 return robots.test(navigator.userAgent); 760 761 } else { 762 return false; 763 }; 764 })(); 765 766 // 767 // CONSENTS 768 // 769 770 function set_consents_in_fpdata( stats = false, pers = false, market = false ){ 771 fpdata.consents = { 772 'can_track_stats' : stats, 773 'can_track_pers' : pers, 774 'can_track_market' : market, 775 }; 776 } 777 778 // GET VARS 779 780 let magic_keyw = FP.getUrlParamByName( fp.main.magic_keyword ), 781 ga4_debug = FP.getUrlParamByName("ga4_debug"); 782 783 // UPDATE COOKIE DATA - fupi_cookies and fpdata.cookies 784 785 if ( magic_keyw && magic_keyw == "off" ){ 786 787 fp.main.track_current_user = false; 788 789 fpdata.cookies = { "stats" : false, "personalisation" : false, "marketing" : false, "disabled" : true }; 790 FP.setCookie( "fp_cookie", JSON.stringify(fpdata.cookies), 7300 ); 791 792 } else if ( ga4_debug && typeof fpdata.cookies == "object" ){ 793 794 fpdata.cookies.ga4_debug = ga4_debug == "on" ? "on" : "off"; 795 FP.setCookie( "fp_ga4_debug", JSON.stringify(fpdata.cookies), 7300 ); 796 797 } else if ( FP.getUrlParamByName("reset_cookies") || ( magic_keyw && ( magic_keyw == "reset" || magic_keyw == "on" ) ) ){ 798 799 FP.deleteCookie("fp_cookie"); 800 fpdata.cookies = false; 801 802 // check if should ask for consent again 803 } else if ( fpdata.cookies && ! fpdata.cookies.disabled && fp.notice && ! fp.notice.dont_ask_again) { 804 805 let pp_pub_changed = fp.notice.priv_policy_update && ( ! fpdata.cookies.pp_pub || fpdata.cookies.pp_pub != fp.notice.priv_policy_update ), 806 tools_changed = fp.tools && ( ! fpdata.cookies.tools || ! fp.tools.every( id => fpdata.cookies.tools.includes(id) ) ); 807 808 if ( pp_pub_changed || tools_changed ) { 809 FP.deleteCookie("fp_cookie"); 810 fpdata.cookies = false; 811 } else { 812 if ( fpdata.cookies.disabled ) fp.main.track_current_user = false; 813 } 814 } 815 816 // CONSENT BANNER - apply page blur and lock scroll 817 818 if ( fp.main.track_current_user && ! fp.main.is_customizer && fp.notice.enabled && ! fpdata.cookies && fp.notice.display_notice ) { 819 820 // BLUR BACKGROUND 821 if ( fp.notice.blur_page ) document.getElementsByTagName( "html" )[0].classList.add("fupi_blur"); 822 823 // LOCK PAGESCROLL 824 if ( fp.notice.scroll_lock ) document.getElementsByTagName( "html" )[0].classList.add("fupi_scroll_lock"); 825 } 826 827 let uses_geo = false; 828 829 /* <fs_premium_only> */ 830 831 if ( fp.main.is_pro ) { 832 833 // MODIFY REFERRER 834 835 if ( fp.track.join_ref && document.referrer.indexOf('http') == 0 ){ 836 837 if ( fp.track.join_ref.includes('fb') ) { 838 if ( !! document.referrer.match(/https*:\/\/.+\.facebook\.com\/*/) || document.referrer == "https://www.facebook.com/" || document.referrer == "http://m.facebook.com" ) { 839 FP.changeReferrer('https://facebook.com/'); 840 } 841 } 842 843 if ( fp.track.join_ref.includes('insta') ) { 844 if ( !! document.referrer.match(/https*:\/\/.+\.instagram\.com\/*/) || document.referrer == "http://instagram.com/" ) { 845 FP.changeReferrer('https://instagram.com/'); 846 } 847 } 848 849 if ( fp.track.join_ref.includes('pin') ) { 850 if ( document.referrer.includes(".pinterest.") && ! document.referrer.includes("/pin/") && ! document.referrer.includes("utm_") ) { 851 FP.changeReferrer('https://pinterest.com/'); 852 } 853 } 854 } 855 856 if ( fp.track.track_non_http ){ 857 if ( document.referrer.length > 0 && document.referrer.indexOf('http') !== 0 ){ 858 if ( ! document.location.search.includes('utm_') && ! document.location.search.includes('gad_s
858ource') ) { 859 FP.changeReferrer('non_http'); 860 } 861 } 862 } 863 864 if ( fp.track.switch_ref ){ 865 FP.changeReferrer('switch_ref'); 866 } 867 } 868 869 function setNoticeMode(){ 870 871 if ( fp.notice.enabled && ( fp.notice.main_mode == "auto_strict" || fp.notice.main_mode == "auto_lax" || fp.notice.main_mode == "manual" ) ) { 872 873 // country unknown 874 if ( fpdata.country == "unknown" ) { 875 876 fp.notice.mode = fp.notice.enable_scripts_after ? fp.notice.enable_scripts_after : "optin"; 877 878 // country known, region unknown 879 } else if ( fpdata.region == "unknown" ){ 880 881 let country_regex = new RegExp( "[\\s,]*" + fpdata.country + "\\s*," ); 882 if ( fp.notice.optin ){ 883 let optin_countries = "," + fp.notice.optin.replace( /\([A-Z,\s]*\)/g, '') + ","; 884 if ( fp.notice.optin == "all" || fp.notice.optin != "none" && !! optin_countries.match( country_regex ) ) fp.notice.mode = "optin"; 885 }; 886 887 if ( ! fp.notice.mode && fp.notice.optout ){ 888 let optout_countries = "," + fp.notice.optout.replace( /\([A-Z,\s]*\)/g, '') + ","; 889 if ( fp.notice.optout == "all" || fp.notice.optout != "none" && !! optout_countries.match( country_regex ) ) fp.notice.mode = "optout"; 890 }; 891 892 if ( ! fp.notice.mode && fp.notice.inform ){ 893 let inform_countries = "," + fp.notice.inform.replace( /\([A-Z,\s]*\)/g, '') + ","; 894 if ( fp.notice.inform == "all" || fp.notice.inform != "none" && !! inform_countries.match( country_regex ) ) fp.notice.mode = "notify"; 895 }; 896 897 if ( ! fp.notice.mode ) fp.notice.mode = "hide"; 898 899 // country & region known 900 } else { 901 902 let country_regex = new RegExp( "[\\s,]*" + fpdata.country + "\\s*," ), 903 region_regex = new RegExp( "[\\s,]*" + fpdata.country + "\\s*\\(.*" + fpdata.region + ".*\\)" ); 904 905 if ( fp.notice.optin ){ 906 let optin_countries = "," + fp.notice.optin + ","; 907 if ( fp.notice.optin == "all" || fp.notice.optin != "none" && ( !! optin_countries.match( region_regex ) || !! optin_countries.match( country_regex ) ) ) fp.notice.mode = "optin"; 908 }; 909 910 if ( ! fp.notice.mode && fp.notice.optout ){ 911 let optout_countries = "," + fp.notice.optout + ","; 912 if ( fp.notice.optout == "all" || fp.notice.optout != "none" && ( !! optout_countries.match( region_regex ) || !! optout_countries.match( country_regex ) ) ) fp.notice.mode = "optout"; 913 }; 914 915 if ( ! fp.notice.mode && fp.notice.inform ){ 916 let inform_countries = "," + fp.notice.inform + ","; 917 if ( fp.notice.inform == "all" || fp.notice.inform != "none" && ( !! inform_countries.match( region_regex ) || !! inform_countries.match( country_regex ) ) ) fp.notice.mode = "notify"; 918 }; 919 920 if ( ! fp.notice.mode ) fp.notice.mode = "hide"; 921 } 922 } else { 923 if ( fp.notice.enabled ) fp.notice.mode = fp.notice.main_mode; 924 } 925 } 926 927 if ( fp.main.is_pro && fp.main.geo ) { // disables geo for users who moved from pro to free when this JS is saved in file 928 929 uses_geo = true; 930 fp.ready = false; 931 932 FP.init = function( send_evt = true ){ 933 setNoticeMode(); 934 FP.updateConsents(); 935 fp.ready = true; 936 if ( send_evt ) FP.sendEvt( 'fp_load_scripts', ['all'] ); 937 } 938 939 // GET LOCATION AND TRIGGER EVERYTHING 940 941 // Get country from URL param... 942 943 let url_country = FP.getUrlParamByName("fp_set_country"); 944 945 if ( url_country ) { 946 if ( fp.main.debug ) console.log( "[FP] Geolocation - country set manually" ); 947 let expire = fp.main.geo && fp.main.remember_geo ? fp.main.remember_geo : 30;
948 FP.setCookie( "fp_country", url_country, expire ); 949 fpdata.country = url_country; 950 FP.init(); 951 952 // If we are not setting country with a URL parameter... 953 954 } else { 955 956 // Check if it was saved in a cookie 957 958 let remembered_country = FP.readCookie("fp_country"); 959 960 // if we have no country in a cookie then we check geolocation 961 if ( ( ! remembered_country || ( remembered_country == "unknown" && fpdata.new_session ) ) && window.fetch ) { 962 963 fpdata.country = "checking"; 964 965 let has_req_geo_settings = true; 966 967 switch ( fp.main.geo ) { 968 case 'ipdata': 969 if ( ! fp.main.ipdata_api_key ) has_req_geo_settings = false; 970 break; 971 case 'cf_worker_url': 972 if ( ! fp.main.cf_worker_url ) has_req_geo_settings = false; 973 break; 974 } 975 976 if ( ! has_req_geo_settings ) { 977 console.error('[FP] Missing configuration data for geolocation method ' + fp.main.geo ); 978 } 979 980 if ( ! fpdata.is_robot && has_req_geo_settings ){ 981 982 if ( fp.main.debug ) console.log( "[FP] Checking location with " + fp.main.geo ); 983 984 // Set timeout that will be cleared on success 985 let geoTimeout = setTimeout(() => { 986 if (fpdata.country === "checking") { 987 fpdata.country = "unknown"; 988 FP.setCookie('fp_country', 'unknown'); 989 if (!fp.ready) { 990 if (fp.main.debug) console.log("[FP] Geolocation timeout"); 991 FP.init(); 992 } 993 } 994 }, 1000); 995 996 // Use the new FP.fetchGeo function 997 FP.fetchGeo( fp.main.geo, { 998 ajaxUrl: fp.main.ajax_url 999 }) 1000 .then(result => { 1001 clearTimeout(geoTimeout); // Prevent duplicate init 1002 1003 fpdata.country = result.country; 1004 if (fp.main.debug) console.log("[FP] Geolocated country: " + result.country ); 1005 1006 fpdata.geo = result.geo; 1007 if (result.region !== 'unknown') fpdata.region = result.region; 1008 1009 let expire = fp.main?.remember_geo || 30; 1010 let cookieValue = result.country; 1011 if (Array.isArray(result.region)) { 1012 cookieValue += '|' + (result.region[0] || "") + "|" + (result.region[1] || ""); 1013 } 1014 1015 FP.setCookie('fp_country', cookieValue, expire); 1016 if (!fp.ready) FP.init(); 1017 }) 1018 .catch(() => { 1019 clearTimeout(geoTimeout); // Prevent duplicate init 1020 fpdata.country = 'unknown'; 1021 FP.setCookie('fp_country', 'unknown'); 1022 if (!fp.ready) FP.init(); 1023 }); 1024 1025 } else { 1026 fpdata.country = 'unknown'; 1027 FP.init(false); 1028 } 1029 1030 // If we have a country in a cookie, then we use it 1031 } else { 1032 1033 let location = remembered_country.split("|"); 1034 1035 fpdata.country = location[0] || "unknown"; 1036 fpdata.region = location[1] || location[2] || "unknown"; 1037 1038 if ( fp.notice.enabled && ! fp.notice.mode ) { 1039 FP.init(false);
1039 // we need to run FP.init() to learn the mode and style of the notice when it is opened by a privacy policy link. We do not send the evt 1040 } else { 1041 FP.updateConsents(); 1042 fp.ready = true; 1043 } 1044 } 1045 } 1046 } 1047 1048 /* </fs_premium_only> */ 1049 1050 if ( ! uses_geo ) { 1051 fpdata.country = 'unknown'; 1052 FP.updateConsents(); 1053 fp.ready = true; 1054 } 1055 1056 // 1057 // CONSENTS - END 1058 // 1059 1060 // Check if WPFP can use cookies 1061 1062 check_if_can_save_wpfp_cookies( true ); 1063 1064 // Get session data from cookies 1065 1066 get_session_data_from_cookies(); 1067 1068 /* <fs_premium_only> */ 1069 // Functions for creatining and updating session cookies 1070 function get_url_params(){ 1071 1072 if ( ! fp.main.is_pro ) return {}; 1073 1074 if ( ! document.location.search ) return {}; 1075 1076 // turn "search" string into an object with param keys and values 1077 let search_str = document.location.search.length > 3 ? document.location.search.substring(1) : false, 1078 params = {}; 1079 1080 if ( search_str ) { 1081 1082 let search_arr = search_str.split('&'); 1083 1084 search_arr.forEach(str => { 1085 let arr = str.split('='); 1086 if ( arr.length == 2 ){ 1087 let param_name = arr[0].replace('?',''), 1088 param_val = arr[1].replace('%20', ' '); // add spaces where they should appear 1089 1090 params[param_name] = param_val; 1091 } 1092 }) 1093 } 1094 1095 return params; 1096 } 1097 /* </fs_premium_only> */ 1098 1099 function create_new_single_session_data( updated_from_free = false ){ 1100 1101 fpdata.current_session = {}; 1102 1103 /* <fs_premium_only> */ 1104 if ( fp.main.is_pro ) { 1105 1106 let url_params = get_url_params(); 1107 1108 fpdata.current_session = { 1109 'url_params' : url_params, 1110 'landing_page' : { 1111 'url' : document.location.href, 1112 'url_params' : url_params, 1113 'referrer' : document.referrer 1114 }, 1115 'page_views' : updated_from_free ? 0 : 1, 1116 'page_types' : {}, 1117 'lead_score' : 0, 1118 'lead_level' : 0, 1119 }; 1120 1121 fpdata.current_session.page_types[fpdata.page_type] = 1; // count views of this pagetype 1122 } 1123 /* </fs_premium_only> */ 1124 1125 FP.setCookie( 'fp_current_session', JSON.stringify(fpdata.current_session), 0, 30 ); // 30 mins 1126 } 1127 1128 function update_single_session_data(){ 1129 if ( ! fpdata.current_session ) return; 1130 /* <fs_premium_only> */ 1131 if ( fp.main.is_pro ) { 1132 1133 // If a WP FP Free saved empty current_session object, then update it to Pro object 1134 if ( ! fpdata.current_session.page_types ) create_new_single_session_data( true ); 1135 1136 fpdata.current_session.page_views++; 1137 fpdata.current_session.page_types[fpdata.page_type] = fpdata.current_session.page_types[fpdata.page_type] ? fpdata.current_session.page_types[fpdata.page_type] + 1 : 1; 1138 } 1139 /* </fs_premium_only> */ 1140 FP.setCookie( 'fp_current_session', JSON.stringify(fpdata.current_session), 0, 30 ); // 30 mins 1141 } 1142 1143 /* <fs_premium_only> */ 1144 function create_new_recent_sessions_data(){ 1145 1146 fpdata.recent_sessions = { 1147 'sessions' : 1, 1148 'page_views' : 1, 1149 'page_types' : {}, 1150 'reactions' : [] // Initialize empty reactions array 1151 }; 1152 1153 fpdata.recent_sessions.page_types[fpdata.page_type] = 1; // count views of this pagetype 1154 1155 FP.setCookie('fp_recent_sessions', JSON.stringify(fpdata.recent_sessions), 30 ); // 30 days 1156 } 1157 1158 function update_recent_sessions_data(){ 1159 if ( ! fpdata.recent_sessions ) return; 1160 if ( fpdata.new_session ) fpdata.recent_sessions.sessions++; // add 1 session only if we start a new session 1161 fpdata.recent_sessions.page_views++; // add 1 pageview 1162 fpdata.recent_sessions.page_types[fpdata.page_type] = fpdata.recent_sessions.page_types[fpdata.page_type] ? fpdata.recent_sessions.page_types[fpdata.page_type] + 1 : 1; // count views of this pagetype 1163 FP.setCookie('fp_recent_sessions', JSON.stringify(fpdata.recent_sessions), 30 );
1163 // 30 days 1164 } 1165 1166 /* </fs_premium_only> */ 1167 1168 // Set or update session data when the page loads 1169 function set_session_data(){ 1170 1171 if ( fp.vars.can_save_wpfp_cookies ) { 1172 1173 fpdata.new_session = ! fpdata.current_session; 1174 1175 ! fpdata.current_session ? create_new_single_session_data() : update_single_session_data(); 1176 /* <fs_premium_only> */ 1177 if ( fp.main.is_pro ) { 1178 ! fpdata.recent_sessions ? create_new_recent_sessions_data() : update_recent_sessions_data(); 1179 } 1180 /* </fs_premium_only> */ 1181 1182 } else { 1183 fpdata.new_session = ! fpdata.refreshed && ! window.sessionStorage['fp_old_session'] && ( window.history.length == 1 || ( window.history.length == 2 && ! document.referrer ) ); 1184 } 1185 1186 fpdata.new_tab = ! fpdata.new_session && ! window.sessionStorage['fp_old_session']; 1187 window.sessionStorage['fp_old_session'] = true; // removed on a new tab 1188 }; 1189 1190 set_session_data(); 1191 1192 // CREATE, UPDATE OR REMOVE SESSION DATA 1193 // triggered after users change cookie preferences or when a page gains focus 1194 1195 // the difference between this Fn and isAnchorLinkToCurrentPage is that this one doesn't check if the link actually works 1196 function isLinkToCurrentPage (link) { 1197 let target_url_obj = new URL( link.href ); 1198 return target_url_obj.origin + target_url_obj.pathname == location.origin + location.pathname; 1199 } 1200 1201 // checks if the link is an anchor to an EXISTING element on the same page 1202 function isAnchorLinkToCurrentPage (link){ 1203 1204 let url = new URL( link.href ), 1205 el = false; 1206 1207 try { 1208 el = FP.findFirst( url.hash ); 1209 } catch (e) { 1210 el = false; 1211 } 1212 1213 return !! el; 1214 }; 1215 1216 function isOutboundLink(el){ 1217 return el.href.indexOf(location.host) == -1 && el.href.indexOf('mailto:') != 0 && el.href.indexOf('tel:') != 0 && el.href.indexOf('http') == 0; 1218 }; 1219 1220 function trackClicks(e, is_middle_click){ 1221 1222 let redirect_stopped = false; 1223 1224 if ( e.target.classList.contains('fupi_click_stopped') ) return; 1225 1226 // PREVENT MULTI CLICKS 1227 // Do not run this function if a visitor clicks the element multiple times in a short time-span 1228 var now = Date.now(); 1229 if ( ! ( ! FP.v.lastClick || now - FP.v.lastClick > fp.track.dblclck_time ) ) return; 1230 FP.v.lastClick = now; 1231 1232 // PREVENT REDIRECTS 1233 1234 // prevent default if a visitor clicked a link that is to be opened on the current tab 1235 var link_el = e.target.closest('a[href]'); 1236 1237 if ( link_el && ! is_middle_click && link_el.target != '_blank' && fp.track.link_click_delay ){ 1238 e.preventDefault(); // prevents redirects 1239 e.stopPropagation(); // prevents other event listeners from firing 1240 e.target.classList.add('fupi_click_stopped'); 1241 e.target.style.pointerEvents = 'none'; 1242 redirect_stopped = true; 1243 if ( fp.main.debug ) console.log('[FP] link-click stopped'); 1244 }; 1245 1246 // GET CLICK DATA 1247 1248 fpdata.clicked = { 1249 'element' : e.target, 1250 'middle' : is_middle_click, 1251 }; 1252 1253 if ( link_el && link_el.href.length > 1 ) { 1254 1255 fpdata.clicked.link = {}; 1256 fpdata.clicked.link.element = link_el; 1257 fpdata.clicked.link.href = link_el.href; 1258 fpdata.clicked.link.is_to_current_page = isLinkToCurrentPage(link_el); 1259 fpdata.clicked.link.target_blank = link_el.target == '_blank'; 1260 1261 fpdata.clicked.link.is_outbound = isOutboundLink(link_el); 1262 fpdata.clicked.link.is_anchor = isAnchorLinkToCurrentPage(link_el); 1263 1264 if ( link_el.href.includes('mailto:') ){ 1265 fpdata.clicked.link.is_email = true; 1266 fpdata.clicked.link.safe_email = link_el.href.replace('mailto:', '').split('@')[0]; 1267 } 1268 1269 if ( link_el.href.includes('tel:') ){
1270 fpdata.clicked.link.is_tel = true; 1271 fpdata.clicked.link.safe_tel = link_el.href.replace('tel:','').slice(-5); 1272 } 1273 } 1274 1275 // RUN QUEUED FNs 1276 1277 FP.doActions( 1278 'click', 1279 false, // no slug 1280 () => { // cb after all functions are run 1281 if ( fpdata.clicked.element.classList.contains('fupi_click_stopped') && typeof fpdata.clicked.element.click == 'function' ) { 1282 fpdata.clicked.element.click(); 1283 fpdata.clicked.element.classList.remove('fupi_click_stopped'); 1284 e.target.style.pointerEvents = ''; 1285 if ( fp.main.debug ) console.log('[FP] Initiated click event after all FP functions'); 1286 } 1287 } 1288 ); 1289 }; 1290 1291 // Add blocked scripts to HTML 1292 function addScriptsToDOM() { 1293 1294 // find scripts which are not loaded 1295 let plain_txt_scripts = FP.findAll('script[data-fupi_class*="fupi_blocked_script"]'); 1296 1297 plain_txt_scripts.forEach( plain_el => { 1298 1299 let dta = plain_el.dataset, 1300 tag_type = dta.fupi_type, 1301 scr_id = dta.fupi_id, 1302 url = dta.fupi_url ?? false, 1303 force_load = dta.fupi_force == '1', 1304 permissions_a = dta.fupi_permiss ? dta.fupi_permiss.split(' ') : [], 1305 geo_a = dta.fupi_geo ? dta.fupi_geo.split(',') : []; 1306 1307 if ( FP.isScriptAllowedToLoad( scr_id, force_load, permissions_a, geo_a ) ) { 1308 if ( tag_type == 'inline' ){ 1309 loadInlineScript( plain_el ); // replaces old tag 1310 } else { 1311 if ( url ){ 1312 FP.createTag( 1313 url, 1314 ()=>{ FP.loaded( scr_id, scr_id ) }, 1315 plain_el, 1316 tag_type 1317 ); 1318 FP.remove(plain_el); 1319 } else { 1320 if (fp.main.debug) console.error('[FP] Couldn\'t load script with ID ' + scr_id + '. Missing src or href values.') 1321 } 1322 } 1323 } 1324 1325 }); 1326 } 1327 1328 // FIRE TAGS WHEN THE DOCUMENT GETS AND LOSES FOCUS 1329 1330 function doPageShowActions(){ 1331 1332 if ( ! fp.vars.page_show_tracked ){ 1333 1334 fp.vars.page_show_tracked = true; 1335 fp.vars.page_hide_tracked = false; 1336 1337 fpdata.doc_in_focus = true; 1338 1339 FP.startActivityTimer(); 1340 1341 var cookies = FP.readCookie('fp_cookie'); 1342 1343 if ( cookies ) { 1344 if ( fpdata.cookies && cookies == JSON.stringify( fpdata.cookies ) ) return; 1345 cookies = JSON.parse(cookies); 1346 fpdata.cookies = cookies; 1347 FP.updateConsents(); 1348 } else { 1349 fpdata.cookies = false; 1350 } 1351 1352 FP.updateSessionData(); 1353 1354 FP.sendEvt( 'fp_load_scripts' ); 1355 1356 if ( fp.actions.page_in_focus ) FP.doActions('page_in_focus'); 1357 } 1358 } 1359 1360 function doPageHideActions(){ 1361 if ( ! fp.vars.page_hide_tracked ) { 1362 fp.vars.page_hide_tracked = true; 1363 fp.vars.page_show_tracked = false; 1364 1365 fpdata.doc_in_focus = false; 1366 FP.stopActivityTimer(); 1367 if ( fp.actions.page_in_blur ) FP.doActions('page_in_blur'); 1368 fpdata.activity.current = 0; 1369 } 1370 } 1371 1372 // ON DYNAMIC URL CHANGES 1373 // URL is set every second with setInterval() and not "active_time_tick", to make the check even when the page is not in focus 1374 1375 let currentUrl = location.href; 1376 1377 setInterval( () => { 1378 1379 fpdata.date = getFormattedDateTime(); 1380 1381 if ( location.href !== currentUrl ) { 1382 currentUrl = location.href; 1383 FP.doActions( 'url_change' ); 1384 } 1385 }, 1000); 1386 1387 // pagehide/show fires on some events but is cross-browser 1388 // !! it fires BEFORE visibilitychanges 1389 // !! when the pageshow event fires the document obj doesn't have updated cookies or localStarage yet, thus we don't use it for "show" 1390 window.addEventListener( "pagehide", e => { doPageHideActions() }, false ); 1391 // window.addEventListener( "pageshow", e => { doPageShowActions('pageshow') }, false ); visibilitychange is universal 1392 1393 // beforeunload doesn't work with prev/next page buttons and has problems on mobiles 1394 window.addEventListener( "beforeunload", e => { doPageHideActions() }, false ); 1395 1396 // visibilitychanges fires on all events but has problems on mobiles and in safari 1397 // !! fires AFTER pagehide/show 1398 // !! when the visibilitychange event fires for "show" the document obj already has updated cookies and localStarage 1399 document.addEventListener( 'visibilitychange', function () { 1400 document.hidden ? doPageHideActions() : doPageShowActions('visibilitychange'); 1401 //if ( fp.page_visibility ) FP.doActions( 'page_visibility' ); 1402 }, false); 1403 1404 document.documentElement.addEventListener('mouseleave', (e) => { 1405 // Don't fire if the page is losing focus (not a real mouse leave) 1406 if (document.hidden) return; 1407 1408 // Check if mouse actually left viewport boundaries 1409 if (e.clientY <= 0 || e.clientX <= 0 || 1410 e.clientX >= window.innerWidth || e.clientY >= window.innerHeight) { 1411 FP.doActions('mouse_leave_window'); 1412 } 1413 }, false ); 1414 1415 1416 // load custom/extra scripts to DOM 1417 document.addEventListener( 'fp_load_scripts', addScriptsToDOM ); 1418 1419 function formSubmitEvents( {target} ){
1420 fpdata.submitted_form = { 'element' : target }; 1421 FP.doActions( 'form_submit' ); 1422 } 1423 1424 // ON FIELD BLUR 1425 document.addEventListener('blur', function(e) { 1426 // Check if the blurred element is a form field 1427 if ( e.target.nodeType === Node.ELEMENT_NODE && e.target.matches('input, textarea, select') ) { 1428 fpdata.last_form_field = e.target; 1429 FP.doActions( 'form_field_blur' ); 1430 } 1431 }, true); 1432 1433 // ON DOM LOADED 1434 1435 function do_when_DOM_loaded(){ 1436 1437 addScriptsToDOM(); 1438 1439 // init actions waiting for DOM loaded 1440 setTimeout ( ()=>{ FP.doActions( ['dom_loaded'] ) }, 250 ); // makes sure that footer JS files loaded and hooked to dom_loaded event 1441 1442 // start listening to form submits 1443 setTimeout( ()=>{ document.addEventListener('submit', formSubmitEvents ) }, fp.track.formsubm_trackdelay ? fp.track.formsubm_trackdelay * 1000 : 1000 ); 1444 1445 // start listening to DOM modifications 1446 if ( fp.track.use_mutation_observer ) FP.detectAddedElement( addedNodes => { 1447 let els = FP.nl2Arr( addedNodes ); 1448 if ( els.length > 0 ) FP.doActions( ['dom_modified'], els ); 1449 } ); 1450 } 1451 1452 if ( document.readyState === "complete" ) { 1453 do_when_DOM_loaded(); 1454 } else { 1455 document.addEventListener('DOMContentLoaded', do_when_DOM_loaded ); 1456 } 1457 1458 // ON MOUSE MOVE 1459 document.addEventListener( 'mousemove', FP.throttle( FP.startActivityTimer, 500 ) ); // This starts the user's activity timer 1460 1461 if ( ! document.hidden) { 1462 FP.startActivityTimer(); 1463 fpdata.doc_in_focus = true; 1464 fp.vars.page_show_tracked = true; 1465 fp.vars.page_hide_tracked = false; 1466 }; 1467 1468 // ON LEFT CLICK 1469 window.addEventListener( 'click', function (e) { 1470 if ( fp.actions.click ) trackClicks(e, false); 1471 }, true); 1472 1473 // ON MIDDLE CLICK 1474 window.addEventListener( 'mouseup', function(e) { 1475 if ( fp.actions.click && e.button == 1) trackClicks(e, true); 1476 }); 1477 1478 FP.loaded('head_helpers'); 1479 1480}; 1481 1482FP.load('head_helpers', 'fupi_top_helpers', ['head_js'] );
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.