PageSourceSearch

https://outcast.ai/wp-content/plugins/bt-bb-ab/js/bt_conversion.js?ver=1.8.11

js outcast.ai collected 2026-10-05 12:21:53 UTC 47,632 bytes, 1,387 lines download raw bytes

1// is user active global vars
2window.abst = {};
3// activity timer
4
5window.abst.timer = localStorage.absttimer === undefined ? {} : JSON.parse(localStorage.absttimer || 0); 
6
7window.abst.currscroll = window.scrollY;
8window.abst.currentMousePos = -1;
9window.abst.oldMousePos = -2;
10window.abst.abactive = true;
11window.abst.timeoutTime = 3000; // how much inactivity before we stop loggin in milliseconds
12window.abst.intervals = {};
13
14//what size, mobile, tablet or desktop 
15if(window.innerWidth < 768)
16  window.abst.size = 'mobile';
17else if(window.innerWidth < 1024)
18  window.abst.size = 'tablet';
19else
20  window.abst.size = 'desktop';
21
22  jQuery(document).ready(function(){
23
24  //todo make visits / conversion wait until we have uuid
25
26    next_page_visit_report();
27
28    if( !btab_vars.is_preview && jQuery('.ab-test-page-redirect').length > 0 ) {
29      jQuery('.ab-test-page-redirect').remove();
30    }
31
32    if( jQuery('[bt_hidden="true"]').length > 0 ) {
33      jQuery('[bt_hidden="true"]').remove();
34    }
35
36  
37    // update scroll status
38    jQuery(document).mousemove(function(event) {
39      window.abst.currentMousePos = event.pageX;
40    });
41    // catch mouse / keyboard action
42    jQuery('body').on('mousedown keydown touchstart', function(event) {
43      userActiveNow();
44    });
45    
46    if(!('abConversionValue' in window.abst))
47      window.abst.abConversionValue = 1;
48
49    window.abst.timerInterval = setInterval(function(){
50      //check if scroll's changed
51
52      if((window.abst.currscroll != window.scrollY) || (window.abst.currentMousePos != window.abst.oldMousePos) )
53      {
54        window.abst.currscroll = window.scrollY;
55        window.abst.oldMousePos = window.abst.currentMousePos;
56        userActiveNow();
57      }
58
59      // check for active class and decrement all active timers
60      if(window.abst.abactive) //for each active timer, increment
61        abstOneSecond();
62
63    },1000); // every second
64
65
66    //conversion things
67    if (typeof conversion_details !== 'undefined' &&  conversion_details)
68    {
69      var eid = null;
70      var variation = null;
71
72      // current p info
73      page_url = window.location.href.replace(window.location.origin,'');
74      if (page_url.charAt(0) == "/") page_url = page_url.substr(1);
75      if (page_url.charAt(page_url.length - 1) == "/") page_url = page_url.substr(0, page_url.length - 1);
76      //loop through each conversion d
77      jQuery.each( conversion_details, function( key, detail ) {
78
79        //regex url matching for url's with *   *about*
80        if (detail.conversion_page_url && page_url) {
81          // Escape special characters in the user input
82          var escapedUrl = detail.conversion_page_url.replace(/([.+?^${}()|[\]\\])/g, '\\$1');
83          // Replace * with a regex pattern (.*)
84          var regexPattern = escapedUrl.replace(/\*/g, '.*');
85          // Create a regular expression object
86          var regex = new RegExp(`^${regexPattern}$`);
87        }
88
89        if(typeof regex !== 'undefined'){
90          if (regex.test(page_url)) {
91              eid = key;
92          }
93        }
94        else if((detail.conversion_page_url === page_url) && (detail.conversion_page_url !== undefined) && (detail.conversion_page_url != ''))  
95        {
96          eid = key;
97        }
98        else if(current_page.includes(detail.conversion_page_id) || current_page.includes(parseInt(detail.conversion_page_id))) 
99        {
100          eid = key;
101        }
102        else
103        {
104          return true; // skip to the next one
105        }
106
107        variation = abstGetCookie('btab_'+eid);
108
109        if(!variation)
110          return true; // skip to the next one
111        
112        variation = JSON.parse(variation);
113
114        //skip if its already converted
115        if( variation.conversion == 1 )
116          return true; // skip to the next one
117        conversionValue = 1;
118        if(window.abst.abConversionValue && detail.use_order_value == true)// woo etc
119          conversionValue = window.abst.abConversionValue;
120
121        bt_experiment_w(eid,variation.variation,'conversion',false,conversionValue);
122    });
123
124    }
125
126    //foreach experiment
127    if (typeof bt_experiments !== 'undefined')
128    {
129      // check for css classes, then add attributes
130      jQuery("[class^='ab-'],[class*=' ab-']").each(function(e){
131        if(jQuery(this).attr('class').includes('ab-var-') || jQuery(this).attr('class').includes('ab-convert'))
132        {
133          allClasses = jQuery(this).attr('class');
134          allClasses = allClasses.split(" "); // into an array
135          thisTestVar = false;
136          thisTestGoal = false;
137          thisTestId = false;
138          thisTestConversion = false;
139          allClasses.forEach(function(element) { 
140            
141            if(element.startsWith('ab-var-'))
142              thisTestVar = element;
143            else if (element.startsWith('ab-goal-'))
144              thisTestGoal = element;
145            else if(element.startsWith('ab-') && !element.includes('ab-convert') )
146              thisTestId = element;          
147            if(element == 'ab-convert')
148              thisTestConversion = true;
149
150          });
151
152          if(thisTestVar !== false && thisTestId !== false)
153          {
154            //we've got variations, do ya thing!
155            jQuery(this).attr('bt-eid',thisTestId.replace("ab-",""));
156            jQuery(this).attr('bt-variation',thisTestVar.replace("ab-var-",""));
157          }
158
159          if(thisTestConversion == true && thisTestId !== false)
160          {
161            // it's a conversion, convert!
162            abstConvert(thisTestId.replace("ab-",""));
163          }
164
165          if(thisTestGoal == true && thisTestId !== false)
166          {
167            //its a goal, record it!
168            abstGoal(thisTestId.replace("ab-",""),thisTestGoal.replace("ab-goal-",""));
169          }
170        }
171
172        if(jQuery(this).attr('class').includes('ab-click-convert-'))
173        {
174          
175          jQuery(this).attr('class').split(" ").forEach(function(element) { // loop through all classes
176            if(element.trim().startsWith('ab-click-convert-'))
177              abClickListener(element.replace("ab-click-convert-",""),"."+element);
178          });
179
180        }
181
182      });
183
184      // legacy probably can be removed, check bricks 
185      jQuery("[data-bt-variation]").each(function(){ 
186        jQuery(this).attr('bt-variation',jQuery(this).attr('data-bt-variation')); 
187        jQuery(this).attr('bt-eid',jQuery(this).attr('data-bt-eid')); 
188      }); 
189
190
191      //fix bricks child attributes
192      //fix bricks, move attr's up one level       
193      document.querySelectorAll(".bricks-element [bt-eid]").forEach(el => {
194        let parent = el.closest('.bricks-element');
195        parent.setAttribute('bt-eid', el.getAttribute('bt-eid'));
196        parent.setAttribute('bt-variation', el.getAttribute('bt-variation'));
197        el.removeAttribute('bt-eid');
198        el.removeAttribute('bt-variation');
199      });
200
201      jQuery.each(bt_experiments, function(experimentId, experiment) {
202
203        // if there is a winner, AND the current page is the default page and AUTOCOMPLETE then just go straight there do not pass go
204        if(experiment.test_winner) 
205        {
206          if(experiment.test_type == 'full_page' && (experiment.full_page_default_page == btab_vars.post_id)) // if full p and the p is this page
207          {
208            if(experiment.test_winner !== btab_vars.post_id) // if its not the current page
209            {
210              if(experiment.page_variations[experiment.test_winner] == undefined) // if its not defined
211              {
212                console.log('split test winner is not found, not redirecting');
213                return false; // skip
214              }
215
216              console.log('Split Test winner is page redirect. Redirecting to '+ experiment.page_variations[experiment.test_winner]);
217              //only do it if its defined
218                window.location.replace( abRedirectUrl(experiment.page_variations[experiment.test_winner]));
219
220              return false;
221            }
222            else // it is the current page so show it
223            {
224              console.log('Test winner is current page. Showing '+ experiment.test_winner);
225              document.body.classList.add('abst-show-page');
226              return false; // skip 2 next experiment
227            }
228
229          }
230          else if(experiment.test_type == 'css_test')
231          {
232            console.log('Split Test CSS winner. Showing '+ experiment.test_winner);
233            jQuery('body').addClass(experiment.test_winner);
234          } // text test winner todo
235          else // on page test
236          {
237            console.log('Split Test winner is on this page. Showing '+ experiment.test_winner);
238            jQuery('*[bt-eid=\"'+experimentId+'\"][bt-variation=\"'+experiment.test_winner+'\"]').addClass('bt-show-variation'); //maybe not necessary anymore now we have CSS?
239            //show variation
240          }
241          return true;
242          //skip this experiment
243        }
244        
245        if(experiment.test_type == "css_test")
246        {
247          for (var i = 0; i < experiment.css_test_variations; i++) {
248            // Code to be executed for each element
249            jQuery('body').append('<script class="bt-css-scripts" bt-variation="test-css-'+experimentId+'-'+ (i+1)+ '" bt-eid="'+experimentId+'"/>');
250          }
251        }
252
253        //full page test handler
254        if(experiment.test_type == 'full_page' && experiment.full_page_default_page == btab_vars.post_id)
255        {
256          //add original do nothing variation
257          jQuery('body').append('<div class="bt-redirect-handle" style="display: none !important" bt-variation="'+experiment.full_page_default_page+'" bt-eid="'+experimentId+'"></div>');
258          //foreach variation
259          jQuery.each(experiment.page_variations,function(varId,variation){
260            jQuery('body').append('<div class="bt-redirect-handle" style="display: none !important" bt-variation="'+varId+'" bt-eid="'+experimentId+'" bt-url="'+variation+'"></div>');
261          });
262        }
263
264        
265        //add conversion click handlers
266        if(experiment.conversion_page == 'selector')
267        {
268          if(experiment.conversion_selector != '')
269          {
270            var conversionSelector = experiment.conversion_selector;
271            abClickListener(experimentId,conversionSelector, 0);
272          }
273        }
274
275
276        // if experiment goals exists
277          //loop through
278          for (var i = 1; i < Object.keys(experiment['goals']).length; i++) {
279            // if experiment.goals[i] key is click
280            //get key name for goal
281            const firstKey = Object.keys(experiment['goals'][i])[0];
282          
283
284            // click selector
285            if(firstKey === 'selector')
286            {
287              abClickListener(experimentId,experiment['goals'][i]['selector'], i);
288            }
289
290            // text subgoall
291            startInverval = false;
292            if(firstKey === 'text')
293            {
294              startInverval = true;
295    
296              convstatus = abstGetCookie('btab_'+experimentId); 
297              if(startInverval && convstatus) // if test exists and not false
298              {
299                convstatus = JSON.parse(convstatus);
300                if (convstatus && convstatus['goals'] && convstatus['goals'][i] == 1)
301                  startInverval = false;
302              }
303    
304              if(experiment['goals'][i]['text'] == '')
305                startInverval = false;
306    
307              //if text exists and not complete
308              if(startInverval)
309              {
310                startTextWatcher(experimentId,experiment['goals'][i]['text'],i);
311              }
312            }
313
314            if(firstKey === 'page')
315            {
316              var goalPage = experiment['goals'][i]['page'];
317
318              if(goalPage == btab_vars.post_id){
319                abstGoal(experimentId,i);
320              }
321            }
322
323            if(firstKey === 'url')
324            {
325              page_url = window.location.href.replace(window.location.origin,'');
326              if (page_url.charAt(0) == "/") page_url = page_url.substr(1);
327              if (page_url.charAt(page_url.length - 1) == "/") page_url = page_url.substr(0, page_url.length - 1);
328
329              goal_url = experiment['goals'][i]['url'].replace(window.location.origin,'');
330              if (goal_url.charAt(0) == "/") goal_url = goal_url.substr(1);
331              if (goal_url.charAt(goal_url.length - 1) == "/") goal_url = goal_url.substr(0, goal_url.length - 1);
332
333              if(page_url == goal_url){
334                abstGoal(experimentId,i);
335                }
336
337            }
338            
339          }
340        
341        
342
343        //text conversion
344        if(experiment.conversion_page == 'text')
345        {
346          startInverval = true;
347          if(!bt_experiments[experimentId])
348            startInverval = false; // not if not defined
349
350          convstatus = abstGetCookie('btab_'+experimentId); 
351          if(startInverval && convstatus) // if test exists and not false
352          {
353            convstatus = JSON.parse(convstatus);
354            if(convstatus.conversion == 1) // if its converted
355              startInverval = false;
356          }
357
358          if(experiment.conversion_text == '')
359            startInverval = false;
360
361          //if text exists and not complete
362          if(startInverval)
363          {
364            startTextWatcher(experimentId,experiment.conversion_text);
365          }
366        }
367
368        //text subgoals
369
370
371
372
373        if(experiment.conversion_page == 'surecart-order-paid' && window.scData  ) // if surecart is slected and surecart js is detected
374        {
375          document.addEventListener('scOrderPaid', function(e) { // add listener
376            console.log('surecart OrderPaid');
377            const checkout = e.detail;
378            if( checkout && checkout.amount_due ) {
379              if( experiment.use_order_value == true)
380                  window.abst.abConversionValue = checkout.amount_due; // set value
381              abstConvert(experimentId, window.abst.abConversionValue);
382            }
383          });   
384      }
385
386
387        if( experiment.conversion_page == 'fingerprint' && !localStorage.getItem("ab-uuid") ) { 
388          console.log("ab-uuid: set fingerprint");
389          setAbFingerprint();
390        } 
391      
392    });
393
394
395      var experiments_el = jQuery('[bt-eid]:not([bt-eid=""])[bt-variation]:not([bt-variation=""])');
396      var current_exp = {};
397      var exp_redirect = {};
398
399      experiments_el.each(function(e) {
400        var me = jQuery(this),
401            experimentId = me.attr('bt-eid'),
402            variation = me.attr('bt-variation'),
403            redirect_url = me.attr('bt-url');
404
405        if( current_exp[experimentId] === undefined ) {
406           current_exp[experimentId] = [];
407          exp_redirect[experimentId] = [];
408        }        
409        if (!current_exp[experimentId].includes(variation)) {
410          current_exp[experimentId].push(variation);
411          exp_redirect[experimentId][variation] = redirect_url;
412        }
413      
414      });
415
416      // add css tests to current exp
417      jQuery.each(bt_experiments, function(experimentId, value) {
418        // Code to be executed for each element
419        if(bt_experiments[experimentId]['test_type'] == 'css_test')
420        {
421          current_exp[experimentId] = []; // create
422          exp_redirect[experimentId] = [];
423
424          for (var i = 1; i <= parseInt(bt_experiments[experimentId]['css_test_variations']); i++) {
425            current_exp[experimentId].push('test-css-'+experimentId+'-'+i);
426            exp_redirect[experimentId]['test-css-'+experimentId+'-'+i] = '';
427          }
428        }
429      });
430     
431      jQuery.each(current_exp, function(experimentId, variations) {
432        //check it exists
433        if( bt_experiments[experimentId] === undefined ) {
434          console.log("ABST: " +'Test ID '+ experimentId +' does not exist.');
435          showSkippedVisitorDefault(experimentId); 
436          return true; // continue to next exp
437        }
438
439        // if there is a winner for the test, then do no more - its already done above
440        if( bt_experiments[experimentId].test_winner) 
441          return true; // continue to next exp
442
443        //if cookie consent isnt done, then show default
444        if ('BorlabsCookie' in window)
445        {
446          // borlabs v2
447          if (typeof window.BorlabsCookie.checkCookieConsent === 'function' &&
448              !window.BorlabsCookie.checkCookieConsent('split-test') &&
449              !window.BorlabsCookie.checkCookieConsent('ab-split-test'))
450            {
451              console.log('Borlabs cookie consent prevented a split test from running');
452              showSkippedVisitorDefault(experimentId);
453              return true; // continue to next exp
454            }
455          //borlabs v3
456          if(typeof window.BorlabsCookie.Consents.hasConsent === 'function')
457          {
458            if(!window.BorlabsCookie.Consents.hasConsent('split-test') && !window.BorlabsCookie.Consents.hasConsent('ab-split-test') )
459            {
460              console.log('Borlabs v3 cookie consent prevented a split test from running');
461              showSkippedVisitorDefault(experimentId);
462              return true; // continue to next exp
463            }
464          }
465        }
466
467
468          
469        if( bt_experiments[experimentId]['is_current_user_track'] == false ) {
470          showSkippedVisitorDefault(experimentId);
471          return true; // continue to next exp
472        }
473
474        // if the test is not published
475        if( bt_experiments[experimentId]['test_status'] !== 'publish' ) {
476          showSkippedVisitorDefault(experimentId);
477          return true; // continue to next exp
478        }
479
480        var targetVisitor = true;
481
482        var btab = abstGetCookie('btab_'+ experimentId);
483        
484        var experimentVariation = '';
485
486        if( !btab ) // no existing data, create
487        {
488          if(bt_experiments[experimentId]['test_type'] == 'css_test'){
489            var randVar = getRandomInt(1, parseInt(bt_experiments[experimentId]['css_test_variations'])) - 1;    
490          }
491          else
492            var randVar = getRandomInt(1, variations.length) - 1;   
493          
494          if(btab_vars.is_free && variations.length > 2){
495            var randVar = getRandomInt(0, 1);  //limit to 2
496            console.log('Free version of AB Split Test is limited to 1 variation. Your others will not be shown. Upgrade: https://absplittest.com/pricing?ref=ug');
497          }
498
499          experimentVariation = variations[randVar];  
500        } 
501        else //parse existing data
502        { 
503          
504          try {
505            var btab_cookie = JSON.parse(btab);
506            experimentVariation = btab_cookie.variation;
507          } catch (err) {
508            console.log('Error parsing cookie data:', err);
509          }
510
511        }
512 
513        var variation_element = false;
514        if(bt_experiments[experimentId]['test_type'] == 'css_test') 
515        {
516          jQuery('body').addClass(experimentVariation); 
517        }
518        else // on page tests
519        {   
520          variation_element = jQuery('*[bt-eid=\"'+experimentId+'\"][bt-variation=\"'+experimentVariation+'\"]'); 
521        } 
522
523        if( btab ){
524            btab = JSON.parse( btab );
525            var redirect_url = exp_redirect[experimentId][experimentVariation];
526            if( redirect_url && !btab_vars.is_preview ) {
527              window.location.replace(  abRedirectUrl( redirect_url) );
528            }
529            else
530            {
531              abstShowPage(); // full page
532              if(variation_element)     
533                variation_element.addClass('bt-show-variation');  // on page
534            }
535            return true; // continue to next exp
536        }
537
538        if( !btab ) { // new user, check tartgeting
539
540          var targetPercentage = bt_experiments[experimentId].target_percentage;
541          
542          if(targetPercentage == '')
543            targetPercentage = 100;
544          
545          var url_query = bt_experiments[experimentId].url_query;
546          urlQueryResult = null;
547          
548          //we've got a url query
549          if(url_query !== '')
550          {
551            
552            var exploded_query = url_query.trim().split("=");
553            if(exploded_query.length == 1) // just the query key
554            {
555              targetVisitor = bt_getQueryVariable(exploded_query[0]);
556            }
557            else if(exploded_query.length == 2) //query key and value
558            {
559              urlQueryResult = bt_getQueryVariable(exploded_query[0]);
560              targetVisitor = exploded_query[1] == urlQueryResult;
561            }
562          }
563          
564          var target_option_device_size = bt_experiments[experimentId].target_option_device_size;
565
566          if(targetVisitor && target_option_device_size != 'all')
567          {
568            var device_size = jQuery(window).width();
569            if(device_size > 767)
570              device_size = 'desktop';
571            else if(device_size > 479)
572              device_size = 'tablet';
573            else
574              device_size = 'mobile';
575
576            targetVisitor = target_option_device_size.includes(device_size);
577
578          }
579
580
581          if(!targetVisitor)
582          {
583            showSkippedVisitorDefault(experimentId);
584            return true;  // continue to next exp
585          }
586          // randomly target users according to percentage
587          var percentage = getRandomInt(1,100);
588          if(targetPercentage < percentage)
589          {        
590            showSkippedVisitorDefault(experimentId,true);
591            console.log('ABST ' + experimentId+' skipped not in percentage target');
592            return true;  // continue to next exp
593          } 
594
595          // no experiment cookie set, calculate and create        
596          bt_experiments[experimentId].variations = bt_get_variations(experimentId);
597        } 
598
599        if(variation_element && !variation_element.length) 
600        {
601          showSkippedVisitorDefault(experimentId);
602          console.log('ABST variation doesnt exist, or doesnt match');
603          return true;  // continue to next exp
604        }
605
606        if (Object.keys(exp_redirect).length > 0)
607        {
608          redirect_url = exp_redirect[experimentId];
609          redirect_url = redirect_url[experimentVariation];
610        }
611        else
612          redirect_url = '';
613
614        // if its css, add it to body   
615        if(variation_element)     
616          variation_element.addClass('bt-show-variation'); 
617        bt_experiment_w(experimentId,experimentVariation,'visit', redirect_url);
618      });
619    }
620
621    // warn users on localhost
622    if(btIsLocalhost())
623      console.info("AB Split Test: It looks like you're on a localhost, using local storage instead of cookies. External Conversion Pixels will not work on Local web servers.");
624
625    window.dispatchEvent(new Event('resize')); // trigger a window resize event. Useful for sliders etc. that dynamically resize
626    jQuery('body').trigger('ab-test-setup-complete'); // the end of the ab testing. do other things if you like with   jQuery('body').bind('ab-test-setup-complete', function() {    //do what you want! });
627
628});
629
630function startTextWatcher(experimentId,word,goalId = null){
631 
632  if(!goalId)
633    goalId = 0;
634
635  if (typeof abst.intervals[experimentId] === 'undefined') {
636    abst.intervals[experimentId] = {};
637  }
638
639  window.abst.intervals[experimentId][goalId] = setInterval(function () {
640    let found = false;
641  
642    // Search within the main page more efficiently
643    jQuery("body").find(":contains('" + word + "')").each(function () {
644      if (jQuery(this).text().indexOf(word) >= 0 && jQuery(this).is(":visible")) {
645        found = true;
646        return false; // Break the loop
647      }
648    });
649  
650    if (!found) {
651      jQuery("iframe").each(function () {
652        try {
653          var iframeBody = jQuery(this).contents().find("body");
654          found = iframeBody.find(":contains('" + word + "')").filter(function () {
655            return jQuery(this).text().indexOf(word) >= 0 && jQuery(this).is(":visible");
656          }).length > 0;
657  
658          if (found){
659            console.log('ABST: ' + experimentId + ' ' + word);
660            return false; // Break the loop
661          } 
662        } catch (error) {
663          //console.error("Error accessing iframe contents:", error);
664        }
665      });
666    }
667  
668      if(found){
669        if(goalId == 0)
670        {
671          abstConvert(experimentId);
672        }
673        else
674        {  
675          abstGoal(experimentId,goalId);
676        }
677        clearInterval(window.abst.intervals[experimentId][goalId]); // Stop the interval after finding the word
678      }
679    }, 1000);
680  }
681  
682
683  function abstConvert(testId = '',orderValue = 1){
684    console.log('abstConvert',testId,orderValue);
685    if(testId !== '')
686    {
687      var btab = abstGetCookie('btab_'+ testId);
688       if(btab)
689       {
690          btab = JSON.parse(btab);
691          if(btab.conversion == 0)
692          {
693            bt_experiment_w(testId,btab.variation,'conversion',false,orderValue);
694            btab.conversion = 1;
695            experiment_vars = JSON.stringify(btab);
696            abstSetCookie('btab_'+ testId, experiment_vars, 1000);   
697            if(abst.intervals[testId]){
698              clearInterval(abst.intervals[testId]);
699            }
700          }
701          else
702          {
703            console.log("ABST: " +bt_experiments[testId].name + ': Visitor has already converted');
704          }
705       }
706       else
707       {
708        if(!bt_experiments[testId])
709          console.log("ABST: " +'Test ID not found or test not active');
710       }
711    }
712  }
713
714  function abstGoal(testId = '',goal = ''){
715    //    console.log('start abstGoal',testId,goal);
716    if(testId !== '' && goal !== '')
717    {
718      var btab = abstGetCookie('btab_'+ testId);
719       if(btab)
720       {
721          btab = JSON.parse(btab);
722          //console.log('btab',btab);
723          if(btab.conversion !== 1) // no goals after conversion
724          {
725            if(Array.isArray(btab.goals))
726            {
727              //if its not in the goal
728              if(btab.goals[goal] !== 0)
729              {
730                btab.goals[goal] = 1; 
731                bt_experiment_w(testId,btab.variation,goal,false,1);
732              }
733              
734              experiment_vars = JSON.stringify(btab);
735              abstSetCookie('btab_'+ testId, experiment_vars, 1000);
736              if(abst.intervals[testId+""+goal])
737              {
738                clearInterval(abst.intervals[testId+""+goal]);
739              }
740            }
741            else
742            {
743              console.log("ABST: " +bt_experiments[testId].name + ': Visitor has already goaled');
744            }
745          } 
746          //else
747            //console.log('no goals after conversion');
748       }
749       else
750       {
751        if(!bt_experiments[testId])
752          console.log("ABST: " +'Test ID not found or test not active');
753       }
754    }
755  }
756    
757function showSkippedVisitorDefault(eid,createCookie = false){
758  
759  if(!window.bt_experiments[eid]){ // if no experiment, show first variations
760    
761      btv = jQuery('*[bt-eid=\"'+eid+'\"]').first().attr('bt-variation');
762      jQuery('*[bt-eid=\"'+eid+'\"][bt-variation=\"'+btv+'\"]').addClass('bt-show-variation');
763      return true;
764  }
765
766  if(bt_experiments[eid].test_winner !== ''){ // if we have a winner
767
768    if(bt_experiments[eid].test_type =="full_page") // full page winner
769    {
770      url = bt_experiments[eid].page_variations[bt_experiments[eid].test_winner];
771      if(url !== undefined)
772      {
773        window.location.replace( abRedirectUrl(url) ); // follow the link w search params
774        return true;
775      }
776      else
777      {
778        console.log("ABST: " +'Full page test complete without matching page winner. Showing current page.');
779      }
780      abstShowPage();
781    }
782
783    if(bt_experiments[eid].test_type == "css_test") // css winner
784    {
785      console.log('css test winner, showing ver ' + bt_experiments[eid]['test_winner']);
786      jQuery("body").addClass('test-css-'+eid+'-'+bt_experiments[eid]['test_winner']); // add winning class
787      return true; // next
788    }
789  }
790
791  if(bt_experiments[eid].test_type == "full_page")
792  {
793    abstShowPage();
794    if(createCookie)
795      skippedCookie(eid,bt_experiments[eid].full_page_default_page);
796
797    return true; // next
798  }
799
800  if(bt_experiments[eid].test_type == "css_test") // css version 1
801  {
802    jQuery("body").addClass('test-css-'+eid+'-1'); // add 1 class
803    if(createCookie)
804      skippedCookie(eid,'test-css-'+eid+'-1');
805    return true; // next
806  }
807  
808  //on page tests only from here
809  
810  if(!eid)
811    return;
812  var foundSpecial = false;
813  jQuery('*[bt-eid=\"'+eid+'\"]').each(function(index, element){
814    var variationName = jQuery(element).attr('bt-variation').toLowerCase();
815    var defaultNames = ["original","one","1","default","standard","a","control"];
816    if(defaultNames.includes(variationName))
817    {
818      btv = variationName;
819      jQuery(element).addClass('bt-show-variation'); // show the matched element
820      foundSpecial = true;
821    }
822  });
823    if(!foundSpecial){
824      btv = jQuery('*[bt-eid=\"'+eid+'\"]').first().attr('bt-variation');
825      jQuery('*[bt-eid=\"'+eid+'\"][bt-variation=\"'+btv+'\"]').addClass('bt-show-variation');
826  }
827
828  if(createCookie)
829    skippedCookie(eid,btv);
830 
831}
832function skippedCookie(eid,btv){
833    var experiment_vars = {
834      eid: eid,
835      variation: btv,
836      conversion: 1,
837      skipped:1
838    };
839    experiment_vars = JSON.stringify(experiment_vars);
840    abstSetCookie('btab_'+ eid, experiment_vars, 1000);
841    return true;
842}
843
844//takes input slug or url and ends url suitable for window/replace
845function abRedirectUrl(url){
846
847  url = url + window.location.search + window.location.hash;
848  // if it starts with http/s dop nothing
849  if(url.startsWith('http') || url.startsWith('/'))
850    return url;
851  else
852    return '/' + url;
853  
854}
855
856function abstOneSecond(){
857  if(Object.keys(window.abst.timer).length > 0)
858  {
859    Object.entries(window.abst.timer).forEach(([ index,item]) => {
860      if(window.abst.timer[index] > -1) // dont decrease below -1
861        window.abst.timer[index] = window.abst.timer[index] - 1;
862
863      if(window.abst.timer[index] == 0){  // convert if its counted down, only fired once
864
865        //console.log('time active converting ' + index);
866        //index could be goal-eid-goalid
867        if(index.includes('goal-'))
868        {
869          var parts = index.split('-');
870          abstGoal(parts[1],parts[2]);
871        }
872        else
873          abstConvert(index);
874      
875      }
876    });
877
878    // update localstorage
879    localStorage.absttimer = JSON.stringify(window.abst.timer); // localstorage need strings
880  }
881}
882
883
884
885function userActiveNow(){
886  window.abst.currscroll = window.scrollY; // update last known scroll n mouse
887  window.abst.abactive = true; // we active
888  clearTimeout(window.abst.timeoutTimer); // delete the old timout
889  window.abst.timeoutTimer = setTimeout(abstActiveTimeout, window.abst.timeoutTime); // create new timeout
890}
891
892function abstActiveTimeout(){
893  window.abst.abactive = false;
894}
895
896
897function getRandomInt(min, max) {
898    min = Math.ceil(min);
899    max = Math.floor(max);
900    return Math.floor(Math.random() * (max - min + 1)) + min;
901}
902
903function abstSetCookie(c_name, value, exdays) {
904    if(btIsLocalhost())
905      return btSetLocal(c_name,value);
906
907    var exdate = new Date();
908    exdate.setDate(exdate.getDate() + exdays);
909    var c_value = escape(value) + ((exdays == null) ? '' : ';path=/; expires=' + exdate.toUTCString()) + "; SameSite=None; Secure";
910
911    document.cookie = c_name + '=' + c_value;
912}
913function deleteCookie(c_name) {
914      if(btIsLocalhost())
915        return btDeleteLocal(c_name);
916
917    document.cookie = c_name+"= ; expires = Thu, 01 Jan 1970 00:00:00 GMT";
918}
919
920function abstGetCookie(c_name) {
921    if(btIsLocalhost())
922      return btGetLocal(c_name);
923
924    var i, x, y, ARRcookies = document.cookie.split(';');
925    for (i = 0; i < ARRcookies.length; i++) {
926        x = ARRcookies[i].substr(0, ARRcookies[i].indexOf('='));
927        y = ARRcookies[i].substr(ARRcookies[i].indexOf('=') + 1);
928        x = x.replace(/^\s+|\s+$/g, '');
929        if (x == c_name) {
930            return unescape(y);
931        }
932    }
933}
934
935function abstShowPage(){
936  jQuery("body").addClass('abst-show-page');
937  jQuery("body",parent.window.document).addClass('abst-show-page'); // bb iframe UI
938}
939
940function btSetLocal(c_name,value){
941    localStorage.setItem(c_name, value);
942}
943
944function btGetLocal(c_name){
945  return localStorage.getItem(c_name);
946}
947
948function btDeleteLocal(c_name){
949  localStorage.removeItem(c_name);
950}
951
952function btIsLocalhost(){
953  return (location.hostname === "localhost" || location.hostname === "127.0.0.1"|| location.hostname.endsWith(".local")|| location.hostname.endsWith(".test"));
954}
955
956function bt_get_variations(eid){
957  
958  variation = [];
959  jQuery('[bt-eid=' + eid + ']').each(function (index, val) {
960    var newVariation = jQuery(this).attr('bt-variation');
961    
962    // Check if the variation already exists in the array
963    if (variation.indexOf(newVariation) === -1) {
964      variation.push(newVariation);
965    }
966  });
967
968  if(btab_vars.is_free)
969  {
970    //only return first 2 variations
971    variation = variation.slice(0,2);
972  }
973
974  return variation;
975}
976
977function bt_experiment_w(eid,variation,type, url,orderValue=1){
978
979  // dont log it if its a skipper or malformed
980  if(variation == '_bt_skip_' || btab_vars.is_preview || !eid || !variation)
981  {
982    return true;
983  }
984
985  // if its a fingerprinter and we dont have a uuid, then wait for it
986  if(bt_experiments[eid].conversion_page == 'fingerprint' && !localStorage.getItem('ab-uuid'))
987  {
988    console.log("bt_exp_w: waiting for fingerprint");
989    setTimeout(bt_experiment_w, 500, eid, variation, type, url,orderValue);
990    return true; //back in 500ms
991  }
992  
993  var data = {
994    'action': 'bt_experiment_w',
995    'eid'  : eid,   
996    'variation'  : variation,   
997    'type'  : type,
998    'size'  : abst.size,
999    'location' : btab_vars.post_id,
1000    'orderValue': orderValue
1001  };
1002
1003  btab_track_event(data); // analytics tagger
1004
1005  var experiment_vars = {
1006    eid: eid,
1007    variation: variation,
1008    conversion: 0,
1009    goals:[],
1010  };
1011
1012  // set up time watchers
1013  if( type == 'visit' && bt_experiments[eid]['conversion_page'] == 'time')
1014  {
1015    window.abst.timer[eid] = bt_experiments[eid]['conversion_time'];
1016  }
1017  //goal time watcher
1018  if( type == 'visit')
1019  {
1020   // console.log(bt_experiments[eid]['goals']);
1021    //foreach goals
1022    jQuery.each(bt_experiments[eid]['goals'], function(key, value) {
1023      // if valuee.time is set
1024      if(value['time'] > 0)
1025      {
1026        window.abst.timer["goal-"+eid + "-"+key] = value['time'];
1027      }
1028    });
1029
1030  }
1031
1032  // set up conversion
1033  if( type == 'conversion' ) 
1034    experiment_vars.conversion = 1;
1035  else if ( type == 'visit' )
1036  {
1037    // not conversion or goal
1038  }
1039  else // goal
1040  {
1041    experiment_vars.goals[type] = 1; // add to goals list
1042  }
1043
1044
1045  //add uuid if necessary
1046  if( bt_experiments[eid]['conversion_page'] == 'fingerprint' )
1047    data.uuid = localStorage.getItem('ab-uuid');
1048
1049  experiment_vars = JSON.stringify(experiment_vars);
1050  abstSetCookie('btab_'+ eid, experiment_vars, 1000);      
1051  //show the page if its not a redirect or external
1052  if(url !== "ex" && !url)
1053  {
1054    abstShowPage(); // show the page
1055  }
1056
1057  //send it to WP to log
1058  // use beacon the data 
1059  console.log('sent beacon',data);
1060  navigator.sendBeacon(bt_ajaxurl+"?action=bt_experiment_w&method=beacon",JSON.stringify(data)); // send the data
1061
1062  // if its a full page redirect, set cookie then redirect then log visit
1063  if(type == 'visit' && url ){
1064    console.log('redirecting after beacon');
1065    window.location.replace(  abRedirectUrl(url));
1066  }
1067  
1068  return true;
1069}
1070
1071async function btab_track_event(data){
1072
1073  //create javascript event with data 
1074  jQuery('body').trigger('abst_event', [data]);
1075  
1076  if(btab_vars.tagging == '0'){
1077    //console.log('event tagging turned off');
1078    return false;
1079  }
1080
1081  window.abeventstarted = new Date().getTime(); // give up sending events after 5 seconds
1082  //set up vals
1083  var trackName = bt_experiments[data.eid].name;
1084  if(trackName == '')
1085    trackName = data.eid;
1086  
1087  var trackCat = data.type;
1088  var trackValue = data.variation;
1089  
1090  //google analytics 4 for all
1091  window.abst.abga4 = setInterval(function(){ 
1092    if(typeof gtag === "function"){  // if using gtag
1093      gtag('event',  'ab_split_test', {  //custom event
1094        'test_name': trackName,
1095        'test_variation': trackValue,
1096        'test_event': trackCat 
1097      });
1098      clearInterval(window.abst.abga4); 
1099      return; 
1100    } 
1101    
1102    if(window.dataLayer && typeof window.dataLayer.push === "function"){  // if using GTM
1103  
1104      window.dataLayer.push({
1105        'event': 'ab_split_test',
1106        'test_name': trackName,
1107        'test_variation': trackValue,
1108        'test_event': trackCat 
1109        });
1110        clearInterval(window.abst.abga4); 
1111      } 
1112
1113    if(new Date().getTime() - window.abeventstarted > 5000)//quit after 5s 
1114    clearInterval(window.abst.abga4); 
1115  },499); 
1116
1117  
1118  
1119  if(btab_vars.is_agency == '1') //agency only after here
1120  {
1121    trackName = "AB Test: " + trackName;
1122    window.abst = window.abst || {};
1123    window.abst.abconvertpartner = window.abst.abconvertpartner || {};
1124    window.abst.abconvertpartner.abawp = false;
1125    window.abst.abconvertpartner.clarity = false;
1126    window.abst.abconvertpartner.gai = false;
1127    window.abst.abconvertpartner.abmix = false;
1128    window.abst.abconvertpartner.abumav = false;
1129    window.abst.abconvertpartner.umami = false;
1130    window.abst.abconvertpartner.cabin = false;
1131    window.abst.abconvertpartner.plausible = false;
1132    window.abst.abconvertpartner.fathom = false;
1133
1134    //tag matomo
1135    var _paq = window._paq = window._paq || [];
1136    _paq.push(['trackEvent', trackName, trackCat, trackValue]);
1137
1138    window.abst.abconvertpartner.timer = setInterval(function(){
1139      if(!window.abst.abconvertpartner.clarity)
1140        if(typeof clarity === "function"){
1141            window.abst.abconvertpartner.clarity = true;
1142            clarity("set", trackName + "-" + trackCat, trackValue);
1143        }
1144
1145      if(!window.abst.abconvertpartner.gai)
1146        if(typeof ga === "function"){
1147          tracker = ga.getAll()[0];
1148          if (tracker)
1149          {
1150              tracker.send("event", trackName, trackCat, trackValue,{nonInteraction: true}); // send non interactive event to GA
1151              window.abst.abconvertpartner.gai = true;
1152          }
1153        }
1154
1155      if(!window.abst.abconvertpartner.fathom)
1156        if(window.fathom){
1157          console.log('fathom trackEvent', trackName + ", " + trackValue + ": " + trackCat); 
1158          window.abst.abconvertpartner.fathom = true;
1159          window.fathom.trackEvent(trackName + ", " + trackValue + ": " + trackCat);
1160        }
1161
1162      if(!window.abst.abconvertpartner.abmix)
1163        if(typeof mixpanel == "object"){
1164          mixpanel.track(trackName, {'type': trackCat,'variation':trackValue}, {send_immediately: true});
1165          window.abst.abconvertpartner.abmix = true;
1166        }
1167
1168      if(!window.abst.abconvertpartner.abumav)
1169        if(typeof usermaven === "function"){
1170          window.abst.abconvertpartner.abumav = true;
1171          usermaven("track", trackName, {
1172            type: trackCat,
1173            variation: trackValue
1174          });
1175        }
1176
1177      if(!window.abst.abconvertpartner.umami)
1178        if(window.umami){
1179          window.abst.abconvertpartner.umami = true;
1180          umami.track(bt_experiments[data.eid].name, {
1181            type: trackCat,
1182            variation: trackValue
1183          });
1184          }
1185 
1186      if(!window.abst.abconvertpartner.cabin)
1187        if(window.cabin){
1188          window.abst.abconvertpartner.cabin = true;
1189          cabin.event(bt_experiments[data.eid].name + ' | ' + trackCat + ' | ' + trackValue);
1190        }
1191
1192      if(!window.abst.abconvertpartner.plausible)
1193        if(window.plausible){
1194          window.abst.abconvertpartner.plausible = true;
1195          plausible(bt_experiments[data.eid].name, {props: {testEvent: trackCat, variation: trackValue}});
1196        }
1197
1198
1199      if(!window.abst.abconvertpartner.abawp)
1200        if(typeof AnalyticsWP === "object"){
1201            window.abst.abconvertpartner.abawp = true;
1202            AnalyticsWP.event('Test: ' + bt_experiments[data.eid].name, {
1203              test_id: data.eid,
1204              test_name: bt_experiments[data.eid].name,
1205              test_variation: trackValue,
1206              test_visit_type: trackCat
1207            });
1208        }
1209  
1210      if(new Date().getTime() - window.abeventstarted > 5000) //quit after 5s
1211        clearInterval(window.abst.abconvertpartner.timer);
1212    },500);
1213   
1214  
1215  } // end agency tracking
1216
1217}
1218
1219// check for a full page tes tvisit cookie
1220function next_page_visit_report(){
1221  var setvisit = abstGetCookie('ab-set-visit');
1222  if(setvisit)
1223  {
1224    try {
1225      setvisit = JSON.parse(setvisit);
1226      
1227      bt_experiment_w(setvisit.eid, setvisit.variation, setvisit.type, false, setvisit.orderValue);
1228    } catch (err) {
1229      console.log('Error parsing next page visitor report data:', err);
1230    } finally {
1231      abstSetCookie('ab-set-visit', false, 1000);
1232    }
1233  }
1234}
1235
1236function bt_getQueryVariable(variable) {
1237  var query = window.location.search.substring(1);
1238  var vars = query.split("&");
1239  for (var i=0;i<vars.length;i++) {
1240    var pair = vars[i].split("=");
1241    if(pair[0] == variable){
1242      if(pair[1] == null)
1243        return true;
1244      return pair[1];
1245    }
1246  }
1247  return(false);
1248}
1249
1250if (!String.prototype.endsWith) {
1251  String.prototype.endsWith = function(search, this_len) {
1252    if (this_len === undefined || this_len > this.length) {
1253      this_len = this.length;
1254    }
1255    return this.substring(this_len - search.length, this_len) === search;
1256  };
1257}
1258
1259
1260
1261//function to find and replace strings uin document, including str
1261ings with formatting like strong em, etc
1262function bt_replace_all(find, replace, location = 'body') {
1263  // Get the element by the provided location
1264  const element = document.querySelector(location);
1265  
1266  // Function to recursively replace text
1267  function replaceText(node) {
1268      if (node.nodeType === Node.TEXT_NODE) { // Check if it's a text node
1269          // Replace text, preserving HTML entities by decoding and encoding
1270          let text = node.textContent;
1271          let div = document.createElement('div');
1272          div.innerHTML = text.replace(new RegExp(find, 'gi'), replace);
1273          node.textContent = div.textContent || div.innerText || "";
1274      } else {
1275          // Otherwise, handle all its children nodes
1276          node.childNodes.forEach(replaceText);
1277      }
1278  }
1279
1280  // Start the text replacement process from the chosen element
1281  replaceText(element);
1282}
1283
1284// Usage example:
1285//bt_replace_all('find text', 'replace text');
1286
1287function bt_replace_all_html(find, replace, location = 'body') {
1288  // Get the element by the provided location
1289  const element = document.querySelector(location);
1290  
1291  // Function to recursively replace HTML
1292  function replaceHTML(node) {
1293      if (node.nodeType === Node.ELEMENT_NODE) { // Check if it's an element node
1294          // Replace HTML, preserving the node structure
1295          node.innerHTML = node.innerHTML.split(find).join(replace);
1296      } else {
1297          // Otherwise, handle all its children nodes
1298          node.childNodes.forEach(replaceHTML);
1299      }
1300  }
1301
1302  // Start the HTML replacement process from the chosen element
1303  replaceHTML(element);
1304}
1305
1306function abClickListener(experimentId,conversionSelector, goalId = 0) {
1307  var testCookie = abstGetCookie('btab_'+experimentId);
1308  if(testCookie)
1309  {
1310    testCookie = JSON.parse(testCookie);
1311    if(goalId == 0)
1312    {
1313      if(testCookie.conversion == 1)
1314      {
1315        //console.log('abClickListener: already converted');
1316        return;
1317      }
1318    }
1319    else // issa goal
1320    {
1321      if(testCookie.goals[goalId] == 1)
1322      {
1323        //console.log('abClickListener: goal already converted');
1324        return;
1325      }      
1326    }
1327  }
1328  var eventType = 'click'; // Default event type
1329  // If a pipe symbol exists, split it into the conversion selector and the event type
1330  if(conversionSelector.indexOf('|') !== -1) {
1331      var conversionParts = conversionSelector.split('|');  
1332      // Check if there are at least two conversionParts
1333      if(conversionParts.length >= 2) {
1334          conversionSelector = conversionParts[0]; // First part is the conversion selector
1335          eventType = conversionParts[1]; // Second part is the event type
1336      }
1337  }
1338
1339  try {
1340    document.addEventListener(eventType, function(event) {
1341      var target = event.target;
1342      while (target && target !== document) {
1343        if (target.matches(conversionSelector)) {
1344          //console.log(eventType + ' conversion on ' + conversionSelector + ' type ' + goalId);
1345          if(goalId > 0)
1346            abstGoal(experimentId,goalId);
1347          else
1348            abstConvert(experimentId);
1349          break;
1350        }
1351        target = target.parentNode;
1352      }
1353    }, true);
1354  } catch(error) {
1355    console.info('ABST: Invalid conversion selector:' +  conversionSelector + ' ' + error + ' ' + goalId); 
1356  }
1357  var iframes = document.querySelectorAll('iframe');
1358  iframes.forEach(function(iframe) {
1359  try {
1360    var iframeDoc = iframe.contentWindow.document;
1361    iframeDoc.addEventListener(eventType, function(event) {
1362      if (event.target.matches(conversionSelector)) {
1363        console.log(eventType + ' IFRAME conversion on ' + conversionSelector);
1364        abstConvert(experimentId);
1365      }
1366    }, true);
1367  } catch (error) {
1368    //console.info('Error accessing cross-origin iframe:', error); // CORS issue, the iframe is not in the same origin and does not allow cross origin access.
1369  }
1370  });
1371}
1372
1373
1374async function setAbFingerprint() {
1375  if(!localStorage.getItem("ab-uuid"))
1376    try {
1377      const module = await import(window.bt_pluginurl + "/js/ab-fingerprint.js");
1378      const fp = await ThumbmarkJS.getFingerprint();
1379      localStorage.setItem("ab-uuid", fp);
1380      console.log("set Fingerprint: " + fp);
1381    } catch (error) {
1382
1383      console.error("Error setting fingerprint:", error);
1384    }
1385  else
1386    console.log("ab-uuid: already set: " + localStorage.getItem("ab-uuid"));
1387}

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.