PageSourceSearch

https://dietdoctor.co.za/wp-content/plugins/pixelyoursite-pro/dist/scripts/public.js?ver=12.2.7

js dietdoctor.co.za collected 2026-10-06 13:15:18 UTC 323,817 bytes, 7,270 lines download raw bytes

1/* global pysOptions */
2
3! function ($, options) {
4    if (options.debug) {
5        console.log('PYS:', options);
6    }
7
8    var uniqueId = {};
9
10    var firstVisit = false;
11
12    var isTrackEventForGA = [];
13
14    var isAdsLoad = false;
15
16    let gtm_variables = {};
17    let gtm_datalayername = "dynamicVariable";
18    var domain = '';
19    if(options.hasOwnProperty("track_cookie_for_subdomains") && options.track_cookie_for_subdomains) {
20        domain = getRootDomain(true);
21    }
22
23
24
25    var loadTags = [];
26
27    var dummyPinterest = function () {
28
29        /**
30         * Public API
31         */
32        return {
33            tag: function() {
34                return "pinterest";
35            },
36            isEnabled: function () {},
37
38            disable: function () {},
39
40            loadPixel: function () {},
41
42            fireEvent: function (name, data) {
43                return false;
44            },
45
46            onAdSenseEvent: function (event) {},
47
48            onClickEvent: function (params) {},
49
50            onWatchVideo: function (params) {},
51
52            onCommentEvent: function (event) {},
53
54            onFormEvent: function (params) {},
55
56            onDownloadEvent: function (params) {},
57
58
59
60            onWooAddToCartOnButtonEvent: function (product_id) {},
61
62            onWooAddToCartOnSingleEvent: function (product_id, qty, product_type, is_external, $form) {},
63
64            onWooRemoveFromCartEvent: function (cart_item_hash) {},
65
66            onWooAffiliateEvent: function (product_id) {},
67
68            onWooPayPalEvent: function (event) {},
69
70            onEddAddToCartOnButtonEvent: function (download_id, price_index, qty) {},
71
72            onEddRemoveFromCartEvent: function (item) {},
73
74            onPageScroll: function (event) {},
75            onTime: function (event) {
76
77            },
78
79        }
80
81    }();
82
83    var dummyBing = function () {
84
85        /**
86         * Public API
87         */
88        return {
89            tag: function() {
90                return "bing";
91            },
92            isEnabled: function () {},
93
94            disable: function () {},
95
96            loadPixel: function () {},
97
98            fireEvent: function (name, data) {
99                return false;
100            },
101
102            onAdSenseEvent: function (event) {},
103
104            onClickEvent: function (params) {},
105
106            onWatchVideo: function (params) {},
107
108            onCommentEvent: function (event) {},
109
110            onFormEvent: function (params) {},
111
112            onDownloadEvent: function (params) {},
113
114
115            onWooAddToCartOnButtonEvent: function (product_id) {},
116
117            onWooAddToCartOnSingleEvent: function (product_id, qty, product_type, is_external, $form) {},
118
119            onWooRemoveFromCartEvent: function (cart_item_hash) {},
120
121            onWooAffiliateEvent: function (product_id) {},
122
123            onWooPayPalEvent: function (event) {},
124
125            onEddAddToCartOnButtonEvent: function (download_id, price_index, qty) {},
126
127            onEddRemoveFromCartEvent: function (item) {},
128            onPageScroll: function (event) {},
129            onTime: function (event) {
130
131            },
132        }
133
134    }();
135
136    var Utils = function (options) {
137
138
139        var Pinterest = dummyPinterest;
140
141        var Bing = dummyBing;
142
143        var gtag_loaded = false;
144
145        var gtm_loaded = false;
146
147        let isNewSession = checkSession();
148
149        let dataLayerName = 'dataLayerPYS';
150
151        let GTMdataLayerName = 'dataLayer';
152
153
154        function loadPixels() {
155
156            if (!options.gdpr.all_disabled_by_api) {
157                if (!options.gdpr.tiktok_disabled_by_api) {
158                    TikTok.loadPixel();
159                }
160
161                if (!options.gdpr.facebook_disabled_by_api) {
162                    Facebook.loadPixel();
163                }
164
165                if (!options.gdpr.analytics_disabled_by_api) {
166                    Analytics.loadPixel();
167                }
168
169                if (!options.gdpr.google_ads_disabled_by_api) {
170                    GAds.loadPixel();
171                }
172
173                if (!options.gdpr.analytics_disabled_by_api) {
174                    GTM.loadPixel();
175                }
176
177                if (!options.gdpr.pinterest_disabled_by_api) {
178                    Pinterest.loadPixel();
179                }
180
181                if (!options.gdpr.bing_disabled_by_api) {
182                    Bing.loadPixel();
183                }
184
185            }
186            if (options.gdpr.consent_magic_integration_enabled && typeof CS_Data !== "undefined") {
187                if (typeof CS_Data.cs_google_analytics_consent_mode !== "undefined" && CS_Data.cs_google_analytics_consent_mode == 1) {
188                    Analytics.loadPixel();
189                }
190                if (typeof CS_Data.cs_google_ads_consent_mode !== "undefined" && CS_Data.cs_google_ads_consent_mode == 1 ) {
191                    GAds.loadPixel();
192                }
193            }
194        }
195
196        /**
197         * WATCHVIDEO UTILS
198         */
199
200        function isJSApiAttrEnabled(url) {
201            return url.indexOf('enablejsapi') > -1;
202        }
203
204        function isOriginAttrEnabled(url) {
205            return url.indexOf('origin') > -1;
206        }
207
208        // Returns key/value pairs of percentages: number of seconds to achieve
209        function getVideoCompletionMarks(duration) {
210
211            var marks = {};
212            var points = [0, 10, 50, 90, 100];
213
214            for (var i = 0; i < points.length; i++) {
215
216                var _point = points[i];
217                var _mark = _point + '%';
218                var _time = duration * _point / 100;
219
220                if (_point === 100) {
221                    _time = _time - 1;
222                }
223
224                // 10% => 123
225                marks[_mark] = Math.floor(_time);
226
227            }
228
229            return marks;
230
231        }
232
233        // Determine if the element is a YouTube video or not
234        function tagIsYouTubeVideo(tag) {
235            var src = tag.src || '';
236            return src.indexOf('youtube.com/embed/') > -1 || src.indexOf('youtube.com/v/') > -1;
237        }
238
239        function tagIsYouTubeAsyncVideo(tag) {
240            if(tag.src && tag.src.indexOf("data:image") !== -1) return false; // video is loaded
241            var keys = Object.keys(tag.dataset);
242            for(var i = 0;i<keys.length;i++) {
243                if(keys[i].toLowerCase().indexOf("src") > -1) {
244                    var src = tag.dataset[keys[i]];
245                    return src.indexOf('youtube.com/embed/') > -1 || src.indexOf('youtube.com/v/') > -1;
246                }
247            }
248            return false; //not find src
249        }
250
251        // Turn embed objects into iframe objects and ensure they have the right parameters
252        function normalizeYouTubeIframe(tag) {
253
254            var loc = window.location;
255            var a = document.createElement('a');
256            a.href = tag.src;
257            a.hostname = 'www.youtube.com';
258            a.protocol = loc.protocol;
259            var tmpPathname = a.pathname.charAt(0) === '/' ? a.pathname : '/' + a.pathname; // IE10 shim
260
261            if (!isJSApiAttrEnabled(a.search)) {
262                a.search = (a.search.length > 0 ? a.search + '&' : '') + 'enablejsapi=1';
263            }
264
265            // for security reasons, YouTube wants an origin parameter set that matches our hostname
266            if (!isOriginAttrEnabled(a.search) && loc.hostname.indexOf('localhost') === -1) {
267
268                var port = loc.port ? ':' + loc.port : '';
269                var origin = loc.protocol + '%2F%2F' + loc.hostname + port;
270
271                a.search = a.search + '&origin=' + origin;
272
273            }
274
275            if (tag.type === 'application/x-shockwave-flash') {
276
277                var newIframe = document.createElement('iframe');
278                newIframe.height = tag.height;
279                newIframe.width = tag.width;
280                tmpPathname = tmpPathname.replace('/v/', '/embed/');
281
282                tag.parentNode.parentNode.replaceChild(newIframe, tag.parentNode);
283
284                tag = newIframe;
285
286            }
287
288            a.pathname = tmpPathname;
289
290            if (tag.src !== a.href + a.hash) {
291                tag.src = a.href + a.hash;
292            }
293
294            return tag;
295
296        }
297
298        // Add event handlers for events emitted by the YouTube API
299        function addYouTubeEvents(iframe) {
300
301            var player = YT.get(iframe.id);
302            if (!player) {
303                player = new YT.Player(iframe, {});
304            }
305
306            if (typeof iframe.pauseFlag === 'undefined') {
307
308                iframe.pauseFlag = false;
309                player.addEventListener('onStateChange', function (evt) {
310                    onYouTubePlayerStateChange(evt, iframe);
311                });
312
313            }
314
315        }
316
317        function addDynYouTubeVideos(el) {
318            // We only bind to iFrames with a YouTube URL with the enablejsapi=1 and
319            // origin=<<hostname>> parameters
320            if (el.tagName === 'IFRAME'
321                && tagIsYouTubeVideo(el)
322                && isJSApiAttrEnabled(el.src)
323                && isOriginAttrEnabled(el.src))
324            {
325                addYouTubeEvents(el);
326            }
327        }
328
329        // Event handler for events emitted from the YouTube API
330        function onYouTubePlayerStateChange(evt, iframe) {
331
332            var stateIndex = evt.data;
333            var player = evt.target;
334            var targetVideoUrl = player.getVideoUrl();
335            var targetVideoId = targetVideoUrl.match(/[?&]v=([^&#]*)/)[1]; // Extract the ID
336            var playerState = player.getPlayerState();
337            var marks = getVideoCompletionMarks(player.getDuration());
338
339            iframe.playTracker = iframe.playTracker || {};
340
341            if (playerState === YT.PlayerState.PLAYING && !iframe.timer) {
342
343                clearInterval(iframe.timer);
344
345                // check every second to see if we've hit any of our percentage viewed marks
346                iframe.timer = setInterval(function () {
347                    checkYouTubeCompletion(player, marks, iframe.videoId);
348                }, 1000);
349
350            } else {
351
352                clearInterval(iframe.timer);
353                iframe.timer = false;
354
355            }
356
357            // playlist edge-case handler
358            if (stateIndex === YT.PlayerState.PLAYING) {
359                iframe.playTracker[targetVideoId] = true;
360                iframe.videoId = targetVideoId;
361                iframe.pauseFlag = false;
362            }
363
364            if (!iframe.playTracker[iframe.videoId]) {
365                return false; // this video hasn't started yet, so this is spam
366            }
367
368            if (stateIndex === YT.PlayerState.PAUSED) {
369
370                if (!iframe.pauseFlag) {
371                    iframe.pauseFlag = true;
372                } else {
373                    return false; // we don't want to fire consecutive pause events
374                }
375
376            }
377
378        }
379
380        // Trigger event if YouTube video mark was reached
381        function checkYouTubeCompletion(player, marks, videoId) {
382
383            var currentTime = player.getCurrentTime();
384
385            player[videoId] = player[videoId] || {};
386
387            for (var key in marks) {
388
389                if (marks[key] <= currentTime && !player[videoId][key]) {
390                    player[videoId][key] = true;
391
392                    var data = player.getVideoData();
393
394                    if (key === '0%') {
395                        key = 'play';
396                    }
397
398                    var params = {
399                        video_type: 'youtube',
400                        video_id: videoId,
401                        video_title: data.title,
402                    };
403
404                    let disable_watch_video = [];
405
406                    //Custom
407                    if ( options.triggerEventTypes.hasOwnProperty( "video_view" ) ) {
408                        Object.entries( options.triggerEventTypes.video_view ).forEach( function ( [ trigger_id, triggers ] ) {
409                            triggers.forEach( function ( trigger ) {
410                                if ( trigger.type === 'youtube' && trigger.rule === videoId ) {
411
412                                    let pixels = Object.keys( options.triggerEvents[ trigger_id ] );
413                                    for ( let i = 0; i < pixels.length; i++ ) {
414                                        let event = Utils.clone( options.triggerEvents[ trigger_id ][ pixels[ i ] ] );
415
416                                        if ( trigger.disable_watch_video ) {
417                                            disable_watch_video.push( pixels[ i ] );
418                                        }
419
420                                        if ( currentTime >= marks[ trigger.value ] ) {
421                                            event.params[ "progress" ] = key;
422                                            Utils.copyProperties( params, event.params );
423
424                                            if ( event.fired !== true ) {
425                                                if ( Utils.isEventInTimeWindow( event.name, event, 'dyn_' + pixels[ i ] + '_' + trigger_id ) ) {
426                                                    event = Utils.getFormFilledData( event );
427                                                    getPixelBySlag( pixels[ i ] ).fireEvent( event.name, event );
428                                                    options.triggerEvents[ trigger_id ][ pixels[ i ] ].fired = true;
429                                                }
430                                            }
431                                        }
432                                    }
433                                }
434                            } )
435                        } )
436                    }
437
438                    // Auto
439                    if( options.automatic.enable_video
440                        && options.automatic.enable_youtube
441                        && options.dynamicEvents.hasOwnProperty("automatic_event_video")
442                    ) {
443                        var pixels = Object.keys(options.dynamicEvents.automatic_event_video);
444
445                        for (var i = 0; i < pixels.length; i++) {
446                            if ( disable_watch_video.includes( pixels[ i ] ) ) {
447                                continue;
448                            }
449                            var event = Utils.clone(options.dynamicEvents.automatic_event_video[pixels[i]]);
450                            event.params["progress"] = key
451                            Utils.copyProperties(params, event.params)
452                            if ( pixels[i] === 'tiktok' ) {
453                                var time_trigger = event.automatic_event_video_trigger;
454                                if ( currentTime >= marks[time_trigger] && event.fired !== true ) {
455                                    getPixelBySlag(pixels[i]).onWatchVideo(event);
456
457                                    //tiktok watch video fire once
458                                    options.dynamicEvents.automatic_event_video[pixels[i]].fired = true;
459                                }
460                            } else {
461                                Utils.copyProperties(Utils.getRequestParam
461s(), event.params);
462                                getPixelBySlag(pixels[i]).onWatchVideo(event);
463                            }
464                        }
465                    }
466
467                    if(key == "play") {
468
469                        $.each(options.triggerEventTypes, function (triggerType, events) {
470                            $.each(events, function (eventId, triggers) {
471                                switch (triggerType) {
472                                    case 'video_play':
473                                        Utils.fireTriggerEvent(eventId);
474                                        break;
475                                }
476
477                            });
478                        });
479                    }
480
481                }
482
483            }
484
485        }
486
487        // Determine if the element is a Vimeo video or not
488        function tagIsVimeoVideo(tag) {
489            var src = tag.src || '';
490            return src.indexOf('player.vimeo.com/video/') > -1;
491        }
492
493        function tagIsAsincVimeoVideo(tag) {
494            if(tag.src) return false; // video is loaded
495            var keys = Object.keys(tag.dataset);
496            for(var i = 0;i<keys.length;i++) {
497                if(keys[i].toLowerCase().indexOf("src") > -1) {
498                    var src = tag.dataset[keys[i]];
499                    return src.indexOf('player.vimeo.com/video/') > -1;
500                }
501            }
502            return false; //not find src
503        }
504
505        function attachVimeoPlayerToTag(tag) {
506            var player = new Vimeo.Player(tag);
507
508            player.getDuration().then(function (pl,seconds) {
509                pl.pysMarks = getVideoCompletionMarks(seconds);
510            }.bind(null,player));
511
512            player.getVideoTitle().then(function (pl,title) {
513                pl.pysVideoTitle = title;
514            }.bind(null,player));
515
516            player.getVideoId().then(function (pl,id) {
517                pl.pysVideoId = id;
518            }.bind(null,player));
519
520            player.pysCompletedMarks = {};
521
522            player.on('play', function () {
523
524                if (this.pysTimer) {
525                    return;
526                }
527
528                clearInterval(this.pysTimer);
529
530                var player = this;
531
532                this.pysTimer = setInterval(function () {
533                    checkVimeoCompletion(player);
534                }, 1000);
535
536            });
537
538            player.on('pause', function () {
539                clearInterval(this.pysTimer);
540                this.pysTimer = false;
541            });
542
543            player.on('ended', function () {
544                clearInterval(this.pysTimer);
545                this.pysTimer = false;
546            });
547        }
548
549        // Trigger event if Vimeo video mark was reached
550        function checkVimeoCompletion(player) {
551
552            player.getCurrentTime().then(function (seconds) {
553
554                for (var key in player.pysMarks) {
555
556                    if (player.pysMarks[key] <= seconds && !player.pysCompletedMarks[key]) {
557
558                        player.pysCompletedMarks[key] = true;
559
560                        if (key === '0%') {
561                            key = 'play';
562                        }
563
564                        var params = {
565                            video_type: 'vimeo',
566                            video_id: player.pysVideoId,
567                            video_title: player.pysVideoTitle,
568                        };
569
570                        let disable_watch_video = [];
571
572                        //Custom
573                        if ( options.triggerEventTypes.hasOwnProperty( "video_view" ) ) {
574                            Object.entries( options.triggerEventTypes.video_view ).forEach( function ( [ trigger_id, triggers ] ) {
575                                triggers.forEach( function ( trigger ) {
576                                    if ( trigger.type === 'vimeo' && trigger.rule == player.pysVideoId ) {
577                                        let pixels = Object.keys( options.triggerEvents[ trigger_id ] );
578                                        for ( let i = 0; i < pixels.length; i++ ) {
579                                            let event = Utils.clone( options.triggerEvents[ trigger_id ][ pixels[ i ] ] );
580
581                                            if ( trigger.disable_watch_video ) {
582                                                disable_watch_video.push( pixels[ i ] );
583                                            }
584
585                                            if ( seconds >= player.pysMarks[ trigger.value ] ) {
586                                                event.params[ "progress" ] 
586= key;
587                                                Utils.copyProperties( params, event.params );
588
589                                                if ( event.fired !== true ) {
590                                                    if ( Utils.isEventInTimeWindow( event.name, event, 'dyn_' + pixels[ i ] + '_' + trigger_id ) ) {
591                                                        event = Utils.getFormFilledData( event );
592                                                        getPixelBySlag( pixels[ i ] ).fireEvent( event.name, event );
593                                                        options.triggerEvents[ trigger_id ][ pixels[ i ] ].fired = true;
594                                                    }
595                                                }
596                                            }
597                                        }
598                                    }
599                                } )
600                            } )
601                        }
602
603                        // Auto
604                        if(options.automatic.enable_video
605                            && options.automatic.enable_vimeo
606                            && options.dynamicEvents.hasOwnProperty("automatic_event_video")
607                        ) {
608                            var pixels = Object.keys(options.dynamicEvents.automatic_event_video);
609
610                            for (var i = 0; i < pixels.length; i++) {
611                                if ( disable_watch_video.includes( pixels[ i ] ) ) {
612                                    continue;
613                                }
614
615                                var event = Utils.clone(options.dynamicEvents.automatic_event_video[pixels[i]]);
616                                event.params["progress"] = key
617                                Utils.copyProperties(params, event.params);
618
619                                if ( pixels[i] === 'tiktok' ) {
620                                    var time_trigger = event.automatic_event_video_trigger;
621                                    if ( seconds >= player.pysMarks[time_trigger] && event.fired !== true ) {
622                                        getPixelBySlag(pixels[i]).onWatchVideo(event);
623
624                                        //tiktok watch video fire once
625                                        options.dynamicEvents.automatic_event_video[pixels[i]].fired = true;
626                                    }
627                                } else {
628                                    Utils.copyProperties(Utils.getRequestParam
628s(), event.params);
629                                    getPixelBySlag(pixels[i]).onWatchVideo(event);
630                                }
631                            }
632                        }
633
634                        if(key == "play") {
635                            $.each(options.triggerEventTypes, function (triggerType, events) {
636                                $.each(events, function (eventId, triggers) {
637                                    switch (triggerType) {
638                                        case 'video_play':
639                                            Utils.fireTriggerEvent(eventId);
640                                            break;
641                                    }
642
643                                });
644                            });
645                        }
646                    }
647
648                }
649
650            });
651
652        }
653
654        /**
655         * COOKIES UTILS
656         */
657
658        var utmTerms = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content' ,'utm_term'];
659        var utmId = ['fbadid', 'gadid', 'padid', 'bingid'];
660        var requestParams = [];
661
662
663        function getDomain(url) {
664
665            url = url.replace(/(https?:\/\/)?(www.)?/i, '');
666
667            if (url.indexOf('/') !== -1) {
668                return url.split('/')[0];
669            }
670
671            return url;
672        }
673
674        function checkSession() {
675
676            if( Cookies.get('pys_start_session') === undefined ||
677                Cookies.get('pys_session_limit') === undefined) {
678                firstVisit = true;
679                return true
680            }
681            return false
682
683        }
684
685        function getTrafficSource() {
686
687            try {
688
689                let referrer = document.referrer.toString(),
690                    source;
691
692                let direct = referrer.length === 0;
693                let internal = direct ? false : referrer.indexOf(options.siteUrl) === 0;
694                let external = !direct && !internal;
695
696                if (external === false) {
697                    source = 'direct';
698                } else {
699                    source = referrer;
700                }
701
702                if (source !== 'direct') {
703                    // leave only domain (Issue #70)
704                    return getDomain(source);
705                } else {
706                    return source;
707                }
708
709            } catch (e) {
710                console.error(e);
711                return 'direct';
712            }
713
714        }
715
716        /**
717         * Return query variables object with where property name is query variable
718         * and property value is query variable value.
719         */
720        function getQueryVars() {
721
722            try {
723
724                var result = {},
725                    tmp = [];
726
727                window.location.search
728                    .substr(1)
729                    .split("&")
730                    .forEach(function (item) {
731
732                        tmp = item.split('=');
733
734                        if (tmp.length > 1) {
735                            result[tmp[0]] = tmp[1];
736                        }
737
738                    });
739
740                return result;
741
742            } catch (e) {
743                console.error(e);
744                return {};
745            }
746
747        }
748
749        function getLandingPageValue() {
750            let name = "pys_landing_page"
751            if(options.visit_data_model === "last_visit") {
752                name = "last_pys_landing_page"
753            }
754            if(Cookies.get(name) && Cookies.get(name) !== "undefined") {
755                return Cookies.get(name);
756            }
757            else if(options.hasOwnProperty("tracking_analytics") && options.tracking_analytics.TrafficLanding){
758                return options.tracking_analytics.TrafficLanding;
759            } else{
760                return "";
761            }
762        }
763        function getTrafficSourceValue() {
764            let name = "pysTrafficSource"
765            if(options.visit_data_model === "last_visit") {
766                name = "last_pysTrafficSource"
767            }
768            if(Cookies.get(name) && Cookies.get(name) !== "undefined") {
769                return Cookies.get(name);
770            }
771            else if(options.hasOwnProperty("tracking_analytics") && options.tracking_analytics.TrafficSource){
772                return options.tracking_analytics.TrafficSource;
773            } else{
774                return "";
775            }
776        }
777
778        /**
779         * Handle alternative GCLID parameter for Safari compatibility
780         * Creates _gcl_aw cookie when alternative parameter is detected and _gcl_aw doesn't exist
781         */
782        function handleAlternativeGclid() {
783            // Check if alternative GCLID is enabled
784            if (!options.GATags || !options.GATags.gclid_alternative_enabled || !options.GATags.gclid_alternative_param) {
785                return;
786            }
787
788            // GDPR consent checks - stop if any consent filter blocks it
789            if (options.gdpr.all_disabled_by_api) {
790                return;
791            }
792            if (options.gdpr.analytics_disabled_by_api) {
793                return;
794            }
795            if (options.cookie.disabled_all_cookie) {
796                return;
797            }
798            if (options.cookie.disabled_google_alternative_id) {
799                return;
800            }
801
802            const alternativeParam = options.GATags.gclid_alternative_param;
803            const queryVars = getQueryVars();
804            
805            // Check if alternative parameter exists in URL
806            if (queryVars[alternativeParam]) {
807                const gclidValue = queryVars[alternativeParam];
808                
809                // Only create _gcl_aw cookie if it doesn't exist
810                if (!Cookies.get('_gcl_aw')) {
811                    // Create _gcl_aw cookie with the alternative parameter value in Google's format
812                    // Format: GCL.{timestamp}.{gclid_value}
813                    const timestamp = Math.floor(Date.now() / 1000);
814                    const cookieValue = 'GCL.' + timestamp + '.' + gclidValue;
815                    
816                    // Set cookie for 90 days (Google's standard)
817                    const expires = new Date();
818                    expires.setTime(expires.getTime() + (90 * 24 * 60 * 60 * 1000));
819                    
820                    Cookies.set('_gcl_aw', cookieValue, { 
821                        expires: expires, 
822                        path: '/', 
823                        domain: domain 
824                    });
825                    
826                    if (options.debug) {
827                        console.log('PYS: Created _gcl_aw cookie from alternative parameter:', alternativeParam, '=', gclidValue);
828                    }
829                }
830            }
831        }
832
833        function getUTMId(useLast = false) {
834            try {
835                let cookiePrefix = 'pys_'
836                let terms = [];
837                if (useLast) {
838                    cookiePrefix = 'last_pys_'
839                }
840                $.each(utmId, function (index, name) {
841                    if (Cookies.get(cookiePrefix + name)) {
842                        terms[name] = Cookies.get(cookiePrefix + name)
843                    }
844                    else if(options.hasOwnProperty("tracking_analytics") && options.tracking_analytics.TrafficUtmsId[name]) {
845                        terms[name] = filterEmails(options.tracking_analytics.TrafficUtmsId[name])
846                    }
847                });
848                return terms;
849            } catch (e) {
850                console.error(e);
851                return [];
852            }
853        }
854        /**
855         * Return UTM terms from request query variables or from cookies.
856         */
857        function getUTMs(useLast = false) {
858
859            try {
860                let cookiePrefix = 'pys_'
861                if(useLast) {
862                    cookiePrefix = 'last_pys_'
863                }
864                let terms = [];
865                $.each(utmTerms, function (index, name) {
866                    if (Cookies.get(cookiePrefix + name)) {
867                        let value = Cookies.get(cookiePrefix + name);
868                        terms[name] = filterEmails(value); // do not allow email in request params (Issue #70)
869                    }
870                    else if(options.hasOwnProperty("tracking_analytics") && options.tracking_analytics.TrafficUtms[name]) {
871                        terms[name] = filterEmails(options.tracking_analytics.TrafficUtms[name])
872                    }
873                });
874
875                return terms;
876
877            } catch (e) {
878                console.error(e);
879                return [];
880            }
881
882        }
883
884        function getDateTime() {
885            var dateTime = new Array();
886            var date = new Date(),
887                days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
888                months = ['January', 'February', 'March', 'April', 'May', 'June',
889                    'July', 'August', 'September', 'October', 'November', 'December'
890                ],
891                hours = ['00-01', '01-02', '02-03', '03-04', '04-05', '05-06', '06-07', '07-08',
892                    '08-09', '09-10', '10-11', '11-12', '12-13', '13-14', '14-15', '15-16', '16-17',
893                    '17-18', '18-19', '19-20', '20-21', '21-22', '22-23', '23-24'
894                ];
895            dateTime.push(hours[date.getHours()]);
896            dateTime.push(days[date.getDay()]);
897            dateTime.push(months[date.getMonth()]);
898            return dateTime;
899        }
900
901        function filterEmails(value) {
902            return Utils.validateEmail(value) ? undefined : value;
903        }
904
905        /**
906         * PUBLIC API
907         */
908        return {
909
910            PRODUCT_SIMPLE : 0,
911            PRODUCT_VARIABLE : 1,
912            PRODUCT_BUNDLE : 2,
913            PRODUCT_GROUPED : 3,
914            utmTerms : utmTerms,
915            utmId : utmId,
916            isNewSession: checkSession(),
917            setHidePixelCookie: function(){
918                let refresh_after_consent = false;
919                if ( !firstVisit && options.gdpr.consent_magic_integration_enabled && window.CS_Data !== undefined && window.CS_Data.cs_refresh_after_consent) {
920                    refresh_after_consent = true;
921                }
922                if( !refresh_after_consent && !firstVisit) return false;
923
924                const url_parts = window.location.href;
925                const url_params = new URLSearchParams(window.location.search);
926                const matchingPixels = ["facebook", "ga", "gtm", "google_ads", "bing", "pinterest", "tiktok"];
927                $.each(matchingPixels, function (index, slug) {
928                    var module = getPixelBySlag(slug);
929                    if (module && module.isEnabled()) {
930                        const fullUrl = window.location.href;
931                        $.each(module.getHidePixel(), function (index, hide_info) {
932                            for (const item of hide_info.hide_tag_contain) {
933                                if (item && fullUrl.includes(item)) {
934                                    let hideTagTimeInMilliseconds = hide_info.hide_tag_time * 60 * 60 * 1000;
935                                    let expiresTime = new Date().getTime() + hideTagTimeInMilliseconds;
936                                    Cookies.set('hide_tag_' + hide_info.pixel, true, { expires: new Date(expiresTime), path: '/' });
937                                    break;
938                                }
939                            }
940                        });
941                    }
942
943                });
944            },
945            hideMatchingPixel: function(pixelValue, slug) {
946                if(Cookies.get('hide_tag_'+pixelValue))
947                {
948                    return true;
949                }
950                return false;
951            },
952            validateEmail: function (email) {
953                var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
954                return re.test(email);
955            },
956            fireEventForAllPixel:function(functionName,events){
957                if (events.hasOwnProperty(Facebook.tag()))
958                    Facebook[functionName](events[Facebook.tag()]);
959                if (events.hasOwnProperty(Analytics.tag()))
960                    Analytics[functionName](events[Analytics.tag()]);
961                if (events.hasOwnProperty(GAds.tag()))
962                    GAds[functionName](events[GAds.tag()]);
963                if (events.hasOwnProperty(Pinterest.tag()))
964                    Pinterest[functionName](events[Pinterest.tag()]);
965                if (events.hasOwnProperty(Bing.tag()))
966                    Bing[functionName](events[Bing.tag()]);
967                if (events.hasOwnProperty(TikTok.tag()))
968                    TikTok[functionName](events[TikTok.tag()]);
969
970                if (events.hasOwnProperty(GTM.tag()))
971                    GTM[functionName](events[GTM.tag()]);
972            },
973
974            getQueryValue:function (name){
975                return getQueryVars()[name];
976            },
977
978            filterEmails: function (value) {
979                return filterEmails(value);
980            },
981
982            setupPinterestObject: function () {
983                Pinterest = window.pys.Pinterest || Pinterest;
984                return Pinterest;
985            },
986
987            setupBingObject: function () {
988                Bing = window.pys.Bing || Bing;
989                return Bing;
990            },
991
992            // Clone all object members to another and return it
993            copyProperties: function (from, to) {
994                for (var key in from) {
995                    if("function" == typeof from[key]) {
996                        continue;
997                    }
998                    to[key] = from[key];
999                }
1000                return to;
1001            },
1002
1003            /**
1004             * Generate unique ID
1005             */
1006            generateUniqueId : function (event) {
1007                if(event.eventID.length == 0 || (event.type == "static" && options.ajaxForServerStaticEvent) || (event.type !== "static" && options.ajaxForServerEvent)) {
1008                    let idKey = event.hasOwnProperty('custom_event_post_id') ? event.custom_event_post_id : event.e_id;
1009                    if (!uniqueId.hasOwnProperty(idKey)) {
1010                        uniqueId[idKey] = pys_generate_token();
1011                    }
1012                    return uniqueId[idKey];
1013                }
1014                else if(event.eventID.length !== 0)
1015                {
1016                    return event.eventID;
1017                }
1018            },
1019
1020            // Flatten object for sendBeacon compatibility
1021            flattenObject: function (obj, prefix = '', res = {}) {
1022                for (const [key, value] of Object.entries(obj)) {
1023                    const prefixedKey = prefix
1024                        ? (Array.isArray(obj) ? `${prefix}[${key}]` : `${prefix}[${key}]`)
1025                        : key;
1026                    if (value !== null && typeof value === 'object' && !(value instanceof File)) {
1027                        this.flattenObject(value, prefixedKey, res);
1028                    } else {
1029                        res[prefixedKey] = value;
1030                    }
1031                }
1032                return res;
1033            },
1034
1035            sendServerAjaxRequest: function ( url, data ) {
1036                // Check if we should use REST API for TikTok or Facebook
1037                if (data.action === 'pys_tiktok_api_event' && window.pysTikTokRest) {
1038                    // Use TikTok REST API
1039                    this.sendRestAPIRequest(data, 'tiktok');
1040                    return;
1041                }
1042                
1043                if (data.action === 'pys_api_event' && data.pixel === 'facebook' && window.pysFacebookRest) {
1044                    // Use Facebook REST API
1045                    this.sendRestAPIRequest(data, 'facebook');
1046                    return;
1047                }
1048                
1049                // Check if sendBeacon is enabled and supported
1050                if (options.useSendBeacon && navigator.sendBeacon) {
1051                    try {
1052                        // Flatten the data object for sendBeacon compatibility
1053                        const flattenedData = this.flattenObject(data);
1054                        const formData = new URLSearchParams();
1055                        
1056                        // Convert flattened data to URLSearchParams
1057                        for (const [key, value] of Object.entries(flattenedData)) {
1058                            if (value !== null && value !== undefined) {
1059                                formData.append(key, value);
1060                            }
1061                        }
1062                        
1063                        // Try to send using sendBeacon
1064                        const success = navigator.sendBeacon(url, formData);
1065                        if (success) {
1066                            return; // Successfully sent via sendBeacon
1067                        }
1068                    } catch (e) {
1069                        // If sendBeacon fails, fall back to jQuery.ajax
1070                        if (options.debug) {
1071                            console.log('PYS: sendBeacon failed, falling back to jQuery.ajax:', e);
1072                        }
1073                    }
1074                }
1075                
1076                // Fallback to jQuery.ajax
1077                jQuery.ajax( {
1078                    type: 'POST',
1079                    url: url,
1080                    data: data,
1081                    headers: {
1082                        'Cache-Control': 'no-cache'
1083                    },
1084                    success: function () {
1085                    },
1086                } );
1087            },
1088            
1089            // Send event via REST API (unified function for TikTok, Facebook, and other platforms)
1090            // Replaces the old sendTikTokRestAPIRequest and sendFacebookRestAPIRequest functions
1091            sendRestAPIRequest: function (data, platform) {
1092                let restApiUrl;
1093                
1094                // Get platform-specific REST API configuration
1095                switch (platform) {
1096                    case 'tiktok':
1097                        restApiUrl = window.pysTikTokRest ? window.pysTikTokRest.restApiUrl : '/wp-json/pys-tiktok/v1/event';
1098                        break;
1099                    case 'facebook':
1100                        restApiUrl = window.pysFacebookRest ? window.pysFacebookRest.restApiUrl : '/wp-json/pys-facebook/v1/event';
1101                        break;
1102                    case 'pinterest':
1103                        restApiUrl = window.pysPinterestRest ? window.pysPinterestRest.restApiUrl : '/wp-json/pys-pinterest/v1/event';
1104                        break;
1105                    default:
1106                        console.error('PYS: Unknown platform for REST API:', platform);
1107                        this.sendAjaxFallback(data);
1108                        return;
1109                }
1110                // Prepare data for REST API
1111                const restApiData = {
1112                    event: data.event,
1113                    event_slug: data.event_slug,
1114                    data: JSON.stringify(data.data || {}),
1115                    ids: JSON.stringify(data.ids || []),
1116                    eventID: data.event_id || data.eventID || '',
1117                    woo_order: data.woo_order || '0',
1118                    edd_order: data.edd_order || '0'
1119                };
1120                
1121                // Try to send using sendBeacon first (if enabled)
1122                if (options.useSendBeacon && navigator.sendBeacon) {
1123                    try {
1124                        const formData = new URLSearchParams();
1125                        for (const [key, value] of Object.entries(restApiData)) {
1126                            formData.append(key, value);
1127                        }
1128                        
1129                        if (navigator.sendBeacon(restApiUrl, formData)) {
1130                            return;
1131                        }
1132                    } catch (e) {
1133                        // sendBeacon failed, continue to fetch
1134                    }
1135                }
1136                
1137                // Try to send using fetch with REST API
1138                if (window.fetch) {
1139                    const headers = {
1140                        'Content-Type': 'application/json'
1141                    };
1142                    
1143                    fetch(restApiUrl, {
1144                        method: 'POST',
1145                        headers: headers,
1146                        body: JSON.stringify(restApiData)
1147                    })
1148                    .then(response => {
1149                        if (!response.ok) {
1150                            throw new Error(platform + ' REST API request failed: ' + response.status);
1151                        }
1152                    })
1153                    .catch(error => {
1154                        // Fallback to AJAX if REST API fails
1155                        if (options.debug) {
1156                            console.log('PYS: ' + platform + ' REST API failed, falling back to AJAX:', error);
1157                        }
1158                        this.sendAjaxFallback(data);
1159                    });
1160                } else {
1161                    // Fallback to AJAX if fetch is not supported
1162                    this.sendAjaxFallback(data);
1163                }
1164            },
1165            
1166            
1167            
1168            // Fallback AJAX method
1169            sendAjaxFallback: function (data) {
1170                jQuery.ajax({
1171                    type: 'POST',
1172                    url: options.ajaxUrl,
1173                    data: data,
1174                    headers: {
1175                        'Cache-Control': 'no-cache'
1176                    },
1177                    success: function () {
1178                    },
1179                });
1180            },
1181
1182            clone: function(obj) {
1183                var copy;
1184
1185                // Handle the 3 simple types, and null or undefined
1186                if (null == obj || "object" != typeof obj) return obj;
1187
1188                // Handle Date
1189                if (obj instanceof Date) {
1190                    copy = new Date();
1191                    copy.setTime(obj.getTime());
1192                    return copy;
1193                }
1194
1195                // Handle Array
1196                if (obj instanceof Array) {
1197                    copy = [];
1198                    for (var i = 0, len = obj.length; i < len; i++) {
1199                        if("function" == typeof obj[i]) {
1200                            continue;
1201                        }
1202                        copy[i] = Utils.clone(obj[i]);
1203                    }
1204                    return copy;
1205                }
1206
1207                // Handle Object
1208                if (obj instanceof Object) {
1209                    copy = {};
1210                    for (var attr in obj) {
1211                        if (obj.hasOwnProperty(attr)) {
1212                            if("function" == typeof obj[attr]) {
1213                                continue;
1214                            }
1215                            copy[attr] = Utils.clone(obj[attr]);
1216                        }
1217                    }
1218                    return copy;
1219                }
1220
1221                return obj;
1222            },
1223
1224            // Returns array of elements with given tag name
1225            getTagsAsArray: function (tag) {
1226                return [].slice.call(document.getElementsByTagName(tag));
1227            },
1228
1229
1230            initializeVideoAPIs: function (options) {
1231                let trigger_has_video_YT, trigger_has_video_Vimeo = false;
1232                if (options.hasOwnProperty('automatic') && options.automatic.enable_video) {
1233                    if ( options.triggerEventTypes.hasOwnProperty( "video_view" ) ) {
1234                        Object.entries( options.triggerEventTypes.video_view ).forEach( function ( [ trigger_id, triggers ] ) {
1235                            triggers.forEach( function ( trigger ) {
1236                                if (trigger.type === 'youtube') {
1237                                    trigger_has_video_YT = true;
1238                                }
1239                                if(trigger.type === 'vimeo'){
1240                                    trigger_has_video_Vimeo = true;
1241                                }
1242                            });
1243                        });
1244                    }
1245                    if(options.automatic.enable_youtube || trigger_has_video_YT){
1246                        Utils.initYouTubeAPI();
1247                    }
1248                    if(options.automatic.enable_vimeo || trigger_has_video_Vimeo){
1249                        Utils.initVimeoAPI();
1250                    }
1251                }
1252            },
1253            /**
1254             * Load and initialize YouTube API
1255             *
1256             * @link: https://developers.google.com/youtube/iframe_api_reference
1257             */
1258            initYouTubeAPI: function () {
1259
1260                // maybe load YouTube JS API
1261                if (typeof window.YT === 'undefined') {
1262                    var tag = document.createElement('script');
1263                    tag.src = '//www.youtube.com/iframe_api';
1264                    var firstScriptTag = document.getElementsByTagName('script')[0];
1265                    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
1266                }
1267
1268                // initialize when API is ready
1269                if ( typeof window.onYouTubeIframeAPIReady !== 'function' ) {
1270
1271                    window.onYouTubeIframeAPIReady = function () {
1272
1273                        // collect all possible YouTube tags
1274                        var potentialVideos = Utils.getTagsAsArray( 'iframe' ).concat( 
1274Utils.getTagsAsArray( 'embed' ) );
1275
1276                        // turn videos into trackable videos with events
1277                        for ( var i = 0; i < potentialVideos.length; i++ ) {
1278                            var video = potentialVideos[ i ];
1279                            if ( tagIsYouTubeVideo( video ) ) {
1280                                var iframe = normalizeYouTubeIframe( video );
1281                                addYouTubeEvents( iframe );
1282                            } else if ( tagIsYouTubeAsyncVideo( video ) ){
1283                                video.addEventListener( "load", function ( evt ) {
1284                                    var iframe = normalizeYouTubeIframe( evt.currentTarget );
1285                                    addYouTubeEvents( iframe );
1286                                } );
1287                            }
1288                        }
1289
1290                        var targets = document.querySelectorAll( '.elementor-widget-video .elementor-wrapper' );
1291
1292                        const config = {
1293                            attributes: false,
1294                            childList: true,
1295                            subtree: true
1296                        };
1297
1298                        const callback = function ( mutationsList, observer ) {
1299                            for ( let mutation of mutationsList ) {
1300                                if ( mutation.type === 'childList' ) {
1301                                    for ( var m = 0; m < mutation.addedNodes.length; m++ ) {
1302                                        addDynYouTubeVideos( mutation.addedNodes[ m ] );
1303                                    }
1304                                }
1305                            }
1306                        };
1307                        // observe elementator widget-video and add event when it add iframe
1308                        for ( var i = 0; i < targets.length; i++ ) {
1309                            const observer = new MutationObserver( callback );
1310                            observer.observe( targets[ i ], config );//maybe remove before add
1311                        }
1312                    }
1313                }
1314            },
1315
1316            /**
1317             * Load and initialize Vimeo API
1318             *
1319             * @link: https://github.com/vimeo/player.js
1320             */
1321            initVimeoAPI: function () {
1322
1323
1324                $(document).ready(function () {
1325
1326                    var potentialVideos = Utils.getTagsAsArray('iframe').concat(Utils.getTagsAsArray('embed'));
1327
1328                    for (var i = 0; i < potentialVideos.length; i++) {
1329                        var tag = potentialVideos[i];
1330                        if (tagIsVimeoVideo(tag)) {
1331                            var nextElementHasClass = $(tag).closest('.elementor-widget-video').find('.elementor-custom-embed-image-overlay');
1332                            if(nextElementHasClass.length > 0) {
1333                                tag.addEventListener("load", function() {
1334                                    attachVimeoPlayerToTag(this);
1335                                });
1336                            }
1337                            else {
1338                                attachVimeoPlayerToTag(tag);
1339                            }
1340
1341
1342                        } else {
1343                            if (tagIsAsincVimeoVideo(tag)) {
1344                                tag.addEventListener("load", function(evt) {
1345                                    attachVimeoPlayerToTag(evt.currentTarget);
1346                                });
1347                            }
1348                        }
1349                    }
1350
1351                });
1352
1353            },
1354
1355            manageCookies: function () {
1356                // Handle alternative GCLID parameter for Safari compatibility
1357                handleAlternativeGclid();
1358                
1359                if (options.gdpr.cookiebot_integration_enabled && typeof Cookiebot !== 'undefined') {
1360                    if (Cookiebot.consented === false && !Cookiebot.consent['marketing'] && !Cookiebot.consent['statistics']) {
1361                        return;
1362                    }
1363                }
1364
1365                let cm_consent_not_expressed = false;
1366                if ( options.gdpr.consent_magic_integration_enabled && window.CS_Data !== undefined && window.CS_Data.cs_refresh_after_consent == 1 ) {
1367                    if ( Cookies.get( 'cs_viewed_cookie_policy' ) === undefined ) {
1368                        cm_consent_not_expressed = true;
1369                    }
1370                }
1371
1372                if( !cm_consent_not_expressed && isNewSession && !options.cookie.disabled_all_cookie && !options.cookie.disabled_start_session_cookie) {
1373                    let duration = options.last_visit_duration * 60000
1374                    var now = new Date();
1375                    now.setTime(now.getTime() + duration);
1376                    Cookies.set('pys_session_limit', true,{ expires: now, path: '/',domain: domain })
1377                    Cookies.set('pys_start_session', true,{ path: '/',domain: domain });
1378                    Utils.setHidePixelCookie();
1379                }
1380
1381                if (!Cookies.get('pbid') && Facebook.isEnabled() && options.ajaxForServerEvent) {
1382                    jQuery.ajax({
1383                        url: options.ajaxUrl,
1384                        dataType: 'json',
1385                        data: {
1386                            action: 'pys_get_pbid'
1387                        },
1388                        success: function (res) {
1389                            if (res.data && res.data.pbid != false && options.send_external_id) {
1390                                if(!(options.cookie.disabled_all_cookie || options.cookie.externalID_disabled_by_api)){
1391                                    var expires = parseInt(options.external_id_expire || 180);
1392                                    Cookies.set('pbid', res.data.pbid, { expires: expires,path: '/',domain: domain });
1393                                }
1394
1395                                if(options.hasOwnProperty('facebook')) {
1396                                    options.facebook.advancedMatching = {
1397                                        ...options.facebook.advancedMatching,  // распыляем текущие значения advancedMatching
1398                                        external_id: res.data.pbid
1399                                    };
1400                                }
1401                            }
1402                        }
1403                    });
1404                } else if (Cookies.get('pbid') && Facebook.isEnabled()){
1405                    if(options.hasOwnProperty('facebook')) {
1406                        options.facebook.advancedMatching = {
1407                            ...options.facebook.advancedMatching,
1408                            external_id: Cookies.get('pbid')
1409                        };
1410                    }
1411                }
1412                let expires = parseInt(options.cookie_duration); //  days
1413                let queryVars = getQueryVars();
1414                let landing = window.location.href.split('?')[0];
1415                try {
1416                    // save data for first visit
1417                    if(Cookies.get('pys_first_visit') === undefined && (!options.cookie.disabled_all_cookie)) {
1418
1419                        if(!options.cookie.disabled_first_visit_cookie)
1420                        {
1421                            Cookies.set('pys_first_visit', true, { expires: expires, path: '/',domain: domain });
1422                        }
1423                        else {
1424                            Cookies.remove('pys_first_visit', { path: '/',domain: domain } )
1425                        }
1426
1427                        if(!options.cookie.disabled_trafficsource_cookie)
1428                        {
1429                            Cookies.set('pysTrafficSource', getTrafficSource(), { expires: expires,path: '/',domain: domain });
1430                        }
1431                        else {
1432                            Cookies.remove('pysTrafficSource', { path: '/',domain: domain })
1433                        }
1434
1435                        if(!options.cookie.disabled_landing_page_cookie && options.enable_lading_page_param)
1436                        {
1437                            Cookies.set('pys_landing_page',landing,{ expires: expires,path: '/',domain: domain });
1438                        }
1439                        else {
1440                            Cookies.remove('pys_landing_page', { path: '/',domain: domain })
1441                        }
1442
1443                        if(!options.cookie.disabled_utmTerms_cookie)
1444                        {
1445                            $.each(utmTerms, function (index, name) {
1446                                if (queryVars.hasOwnProperty(name)) {
1447                                    Cookies.set('pys_' + name, queryVars[name], { expires: expires,path: '/',domain: domain });
1448                                } else {
1449                                    Cookies.remove('pys_' + name, { path: '/',domain: domain })
1450                                }
1451                            });
1452                        }
1453                        else {
1454                            $.each(utmTerms, function (index, name) {
1455                                Cookies.remove('pys_' + name, { path: '/',domain: domain })
1456                            });
1457                        }
1458
1459                        if(!options.cookie.disabled_utmId_cookie)
1460                        {
1461                            $.each(utmId,function(index,name) {
1462                                if (queryVars.hasOwnProperty(name)) {
1463                                    Cookies.set('pys_' + name, queryVars[name], { expires: expires,path: '/',domain: domain });
1464                                } else {
1465                                    Cookies.remove('pys_' + name, { path: '/',domain: domain })
1466                                }
1467                            })
1468                        }
1469                        else {
1470                            $.each(utmId, function (index, name) {
1471                                Cookies.remove('pys_' + name, { path: '/',domain: domain })
1472                            });
1473                        }
1474
1475                    }
1476
1477                    // save data for last visit if it new session
1478                    if(isNewSession && (!options.cookie.disabled_all_cookie)) {
1479                        if(!options.cookie.disabled_trafficsource_cookie)
1480                        {
1481                            Cookies.set('last_pysTrafficSource', getTrafficSource(), { expires: expires,path: '/',domain: domain });
1482                        }
1483                        else {
1484                            Cookies.remove('last_pysTrafficSource', { path: '/',domain: domain })
1485                        }
1486
1487                        if(!options.cookie.disabled_landing_page_cookie && options.enable_lading_page_param)
1488                        {
1489                            Cookies.set('last_pys_landing_page',landing,{ expires: expires,path: '/',domain: domain });
1490                        }
1491                        else {
1492                            Cookies.remove('last_pys_landing_page', { path: '/',domain: domain })
1493                        }
1494
1495                        if(!options.cookie.disabled_utmTerms_cookie)
1496                        {
1497                            $.each(utmTerms, function (index, name) {
1498                                if (queryVars.hasOwnProperty(name)) {
1499                                    Cookies.set('last_pys_' + name, queryVars[name], { expires: expires,path: '/',domain: domain });
1500                                } else {
1501                                    Cookies.remove('last_pys_' + name, { path: '/',domain: domain })
1502                                }
1503                            });
1504                        }
1505                        else {
1506                            $.each(utmTerms, function (index, name) {
1507                                Cookies.remove('last_pys_' + name, { path: '/',domain: domain })
1508                            });
1509                        }
1510
1511                        if(!options.cookie.disabled_utmId_cookie)
1512                        {
1513                            $.each(utmId,function(index,name) {
1514                                if (queryVars.hasOwnProperty(name)) {
1515                                    Cookies.set('last_pys_' + name, queryVars[name], { expires: expires,path: '/',domain: domain });
1516                                } else {
1517                                    Cookies.remove('last_pys_' + name, { path: '/',domain: domain })
1518                                }
1519                            })
1520                        }
1521                        else {
1522                            $.each(utmId, function (index, name) {
1523                                Cookies.remove('last_pys_' + name, { path: '/',domain: domain })
1524                            });
1525                        }
1526
1527                    }
1528                    if(options.cookie.disabled_start_session_cookie) {
1529                        Cookies.remove('pys_start_session', { path: '/',domain: domain })
1530                        Cookies.remove('pys_session_limit', { path: '/',domain: domain })
1531                    }
1532                    if(options.cookie.disabled_all_cookie)
1533                    {
1534                        Cookies.remove('pys_first_visit', { path: '/',domain: domain })
1535                        Cookies.remove('pysTrafficSource', { path: '/',domain: domain })
1536                        Cookies.remove('pys_landing_page', { path: '/',domain: domain })
1537                        Cookies.remove('last_pys_landing_page', { path: '/',domain: domain })
1538                        Cookies.remove('last_pysTrafficSource', { path: '/',domain: domain })
1539                        Cookies.remove('pys_start_session', { path: '/',domain: domain })
1540                        Cookies.remove('pys_session_limit', { path: '/',domain: domain })
1541                        $.each(Utils.utmTerms, function (index, name) {
1542                            Cookies.remove('pys_' + name, { path: '/',domain: domain })
1543                        });
1544                        $.each(Utils.utmId,function(index,name) {
1545                            Cookies.remove('pys_' + name, { path: '/',domain: domain })
1546                        })
1547                        $.each(Utils.utmTerms, function (index, name) {
1548                            Cookies.remove('last_pys_' + name, { path: '/',domain: domain })
1549                        });
1550                        $.each(Utils.utmId,function(index,name) {
1551                            Cookies.remove('last_pys_' + name, { path: '/',domain: domain })
1552                        });
1553                    }
1554                } catch (e) {
1555                    console.error(e);
1556                }
1557            },
1558
1559            initializeRequestParams: function () {
1560
1561                if (options.trackTrafficSource) {
1562                    requestParams.traffic_source = getTrafficSourceValue();
1563                }
1564
1565                if (options.trackUTMs) {
1566
1567                    var utms = getUTMs(options.visit_data_model === "last_visit");
1568
1569                    $.each(utmTerms, function (index, term) {
1570                        if (term in utms) {
1571                            requestParams[term] = utms[term];
1572                        }
1573                    });
1574
1575                }
1576
1577
1578                var dateTime = getDateTime();
1579                if(options.enable_event_time_param) {
1580                    requestParams.event_hour = dateTime[0];
1581                }
1582
1583                if(options.enable_event_day_param) {
1584                    requestParams.event_day = dateTime[1];
1585                }
1586                if(options.enable_event_month_param) {
1587                    requestParams.event_month = dateTime[2];
1588                }
1589
1590                if(options.enable_lading_page_param){
1591                    requestParams.landing_page = getLandingPageValue();
1592                }
1593            },
1594
1595            getRequestParams: function () {
1596                return requestParams;
1597            },
1598
1599            /**
1600             * DOWNLOAD DOCS
1601             */
1602
1603            getLinkExtension: function (link) {
1604
1605                // Remove anchor, query string and everything before last slash
1606                link = link.substring(0, (link.indexOf("#") === -1) ? link.length : link.indexOf("#"));
1607                link = link.substring(0, (link.indexOf("?") === -1) ? link.length : link.indexOf("?"));
1608                link = link.substring(link.lastIndexOf("/") + 1, link.length);
1609
1610                // If there's a period left in the URL, then there's a extension
1611                if (link.length > 0 && link.indexOf('.') !== -1) {
1612                    link = link.substring(link.lastIndexOf(".") + 1); // Remove everything but what's after the first period
1613                    return link;
1614                } else {
1615                    return "";
1616                }
1617            },
1618
1619            getLinkFilename: function (link) {
1620
1621                // Remove anchor, query string and everything before last slash
1622                link = link.substring(0, (link.indexOf("#") === -1) ? link.length : link.indexOf("#"));
1623                link = link.substring(0, (link.indexOf("?") === -1) ? link.length : link.indexOf("?"));
1624                link = link.substring(link.lastIndexOf("/") + 1, link.length);
1625
1626                // If there's a period left in the URL, then there's a extension
1627                if (link.length > 0 && link.indexOf('.') !== -1) {
1628                    return link;
1629                } else {
1630                    return "";
1631                }
1632            },
1633
1634            /**
1635             * CUSTOM EVENTS
1636             */
1637
1638            setupMouseOverClickEvents: function (eventId, triggers) {
1639
1640                // Non-default binding used to avoid situations when some code in external js
1641                // stopping events propagation, eg. returns false, and our handler will never called
1642                document.addEventListener('mouseover', function(event) {
1643                    var matchedElements = Array.from(document.querySelectorAll(triggers));
1644                    var clickedElement = event.target;
1645                    var closestMatch = clickedElement.closest(triggers);
1646                    if (matchedElements.includes(clickedElement) || closestMatch){
1647                        if (event.target.classList.contains('pys-mouse-over-' + eventId)) {
1648                            return true;
1649                        } else {
1650                            event.target.classList.add('pys-mouse-over-' + eventId);
1651                        }
1652
1653                        Utils.fireTriggerEvent(eventId);
1654                    }
1655                });
1656
1657
1658            },
1659
1660            setupFormFieldEvents: function (eventId, triggers) {
1661                triggers.forEach(function(trigger) {
1662                    let eventType = 'input';
1663
1664                    if (['checkbox', 'radio', 'select'].includes(trigger.type)) {
1665                        eventType = 'change';
1666                    } else if (['text', 'email', 'tel'].includes(trigger.type)) {
1667                        eventType = 'blur';
1668                    }
1669
1670                    const form = document.querySelector(trigger.form);
1671                    if (!form) return;
1672
1673                    const field = form.querySelector(trigger.field); // ищем поле ТОЛЬКО внутри формы
1674                    if (!field) return;
1675
1676                    field.addEventListener(eventType, function (event) {
1677                        Utils.fireTriggerEvent(eventId);
1678                    }, true);
1679                });
1680            },
1681
1682            setupCSSClickEvents: function (eventId, triggers) {
1683                // Non-default binding used to avoid situations when some code in external js
1684                // stopping events propagation, eg. returns false, and our handler will never called
1685                // add event to document to support dyn class
1686                document.addEventListener('click', function(event) {
1687                    let matchedElements = Array.from(document.querySelectorAll(triggers)),
1688                        clickedElement = event.target,
1689                        closestMatch = clickedElement.closest(triggers);
1690
1691                    if (matchedElements.includes(clickedElement) || closestMatch){
1692                        Utils.fireTriggerEvent(eventId);
1693                    }
1694                }, true);
1695            },
1696
1697            setupURLClickEvents: function () {
1698
1699                if( !options.triggerEventTypes.hasOwnProperty('url_click') ) {
1700                    return;
1701                }
1702                // Non-default binding used to avoid situations when some code in external js
1703                // stopping events propagation, eg. returns false, and our handler will never called
1704                document.addEventListener('click', function(event) {
1705                    let anchor = event.target.closest('a');
1706
1707                    if (anchor) {
1708                        var url = anchor.getAttribute('href');
1709                        if (url) {
1710                            Object.entries(options.triggerEventTypes.url_click).forEac
1710h(function ([eventId, triggers]) {
1711                                triggers.forEach(function (trigger) {
1712                                    if (Utils.compareUrl(url, trigger.value, trigger.rule)) {
1713                                        Utils.fireTriggerEvent(eventId);
1714                                    }
1715                                });
1716                            });
1717                        }
1718                    }
1719                }, true);
1720
1721            },
1722
1723            removeUrlDomain(url) {
1724                if(url.indexOf("/#") > -1) {
1725                    url = url.substring(0, url.indexOf("/#"));
1726                }
1727                return url.replace('http://','')
1728                    .replace('https://','')
1729                    .replace('www.','')
1730                    .trim()
1731                    .replace(/^\/+/g, '')
1732
1733            },
1734
1735            compareUrl: function(base,url,rule){
1736
1737                if(url == "*" || url == '') return true;
1738
1739                base = Utils.removeUrlDomain(base)
1740                url = Utils.removeUrlDomain(url)
1741
1742                if(rule == 'match') {
1743                    return url == base;
1744                } else {
1745                    return base.indexOf(url) !== -1
1746                }
1747
1748            },
1749
1750            setupScrollPosEvents: function (eventId, triggers) {
1751
1752                var scrollPosThresholds = {},
1753                    docHeight = $(document).height() - $(window).height();
1754
1755                // convert % to absolute positions
1756                $.each(triggers, function (index, scrollPos) {
1757
1758                    // convert % to pixels
1759                    scrollPos = docHeight * scrollPos / 100;
1760                    scrollPos = Math.round(scrollPos);
1761
1762                    scrollPosThresholds[scrollPos] = eventId;
1763
1764                });
1765
1766                $(document).on("scroll",function () {
1767
1768                    var scrollPos = $(window).scrollTop();
1769
1770                    $.each(scrollPosThresholds, function (threshold, eventId) {
1771
1772                        // position has not reached yes
1773                        if (scrollPos <= threshold) {
1774                            return true;
1775                        }
1776
1777                        // fire event only once
1778                        if (eventId === null) {
1779                            return true;
1780                        } else {
1781                            scrollPosThresholds[threshold] = null;
1782                        }
1783
1784                        Utils.fireTriggerEvent(eventId);
1785
1786                    });
1787
1788                });
1789
1790            },
1791            setupCommentEvents : function (eventId,triggers) {
1792                $('form.comment-form').on("submit",function () {
1793                    Utils.fireTriggerEvent(eventId);
1794                });
1795            },
1796
1797            setupEmailLinkEvents: function ( events ) {
1798
1799                $( document ).on( 'click', 'a', function ( event ) {
1800                    let anchor = event.target.closest('a');
1801
1802                    if (anchor) {
1803                        let url = anchor.getAttribute('href');
1804                        if (url && (url.startsWith('mailto:') || url.startsWith('tel:'))) {
1805
1806                            let sendEventIds = [],
1807                                disabled_for_pixels = [],
1808                                disabled_email_action = false;
1809
1810                            $.each(events, function (eventId, trigger_group) {
1811                                url = url.replace('mailto:', '').replace('tel:', '');
1812                                trigger_group.forEach(function (triggers) {
1813                                    triggers.rules.forEach(function (trigger) {
1814                                        if (Utils.compareUrl(url, trigger.value, trigger.rule)) {
1815                                            sendEventIds.push(eventId);
1816                                            if (triggers.hasOwnProperty('disabled_email_link') && triggers.disabled_email_link) {
1817                                                disabled_email_action = true;
1818                                                if (options.triggerEvents.hasOwnProperty(eventId)) {
1819                                                    disabled_for_pixels.push(...Object.keys(options.triggerEvents[eventId]));
1820                                                }
1821                                            }
1822                                        }
1823                                    });
1824                                })
1825                            })
1826
1827                            if (sendEventIds.length > 0) {
1828                                sendEventIds.forEach(function (sendEventId) {
1829                                    Utils.fireTriggerEvent(sendEventId);
1830                                })
1831                            }
1832                            setupEmailLinks(disabled_for_pixels);
1833                        }
1834                    }
1835                } )
1836            },
1837
1838            /**
1839             * Events
1840             */
1841
1842            isEventInTimeWindow: function (eventName, event, prefix) {
1843
1844                if(event.hasOwnProperty("hasTimeWindow") && event.hasTimeWindow) {
1845                    var cookieName = prefix+"_"+eventName;
1846                    var now = new Date().getTime();
1847
1848                    if(Cookies.get(cookieName) !== undefined) {
1849
1850                        var lastTimeFire = Cookies.get(cookieName);
1851                        var fireTime = event.timeWindow * 60*60*1000;
1852
1853                        if( now - lastTimeFire > fireTime) {
1854                            Cookies.set(cookieName,now, { expires: event.timeWindow / 24.0, path: '/'} );
1855                        } else {
1856                            return false;
1857                        }
1858                    } else {
1859                        Cookies.set(cookieName,now, { expires: event.timeWindow / 24.0, path: '/'} );
1860                    }
1861                }
1862                return true
1863            },
1864
1865            fireTriggerEvent: function (eventId) {
1866
1867                if (!options.triggerEvents.hasOwnProperty(eventId)) {
1868                    return;
1869                }
1870
1871                var event = {};
1872                var events = options.triggerEvents[eventId];
1873
1874                if (events.hasOwnProperty('facebook')) {
1875                    event = events.facebook;
1876                    if(Utils.isEventInTimeWindow(event.name,event,"dyn_facebook_"+eventId)) {
1877                        event = Utils.getFormFilledData(event);
1878                        Facebook.fireEvent(event.name, event);
1879                    }
1880                }
1881
1882                if (events.hasOwnProperty('ga')) {
1883                    event = events.ga;
1884                    if(Utils.isEventInTimeWindow(event.name,event,"dyn_ga_"+eventId)) {
1885                        event = Utils.getFormFilledData(event);
1886                        Analytics.fireEvent(event.name, event);
1887                    }
1888                }
1889
1890                if (events.hasOwnProperty('google_ads')) {
1891                    event = events.google_ads;
1892                    if(Utils.isEventInTimeWindow(event.name,event,"dyn_google_ads_"+eventId)) {
1893                        event = Utils.getFormFilledData(event);
1894                        GAds.fireEvent(event.name, event);
1895                    }
1896                }
1897
1898                if (events.hasOwnProperty('pinterest')) {
1899                    event = events.pinterest;
1900                    if(Utils.isEventInTimeWindow(event.name,event,"dyn_pinterest_"+eventId)) {
1901                        event = Utils.getFormFilledData(event);
1902                        Pinterest.fireEvent(event.name, event);;
1903                    }
1904                }
1905
1906                if (events.hasOwnProperty('bing')) {
1907                    event = events.bing;
1908                    if(Utils.isEventInTimeWindow(event.name,event,"dyn_bing_"+eventId)) {
1909                        event = Utils.getFormFilledData(event);
1910                        Bing.fireEvent(event.name, event);;
1911                    }
1912                }
1913                if (events.hasOwnProperty('tiktok')) {
1914                    event = events.tiktok;
1915                    if(Utils.isEventInTimeWindow(event.name,event,"dyn_tiktok_"+eventId)) {
1916                        event = Utils.getFormFilledData(event);
1917                        TikTok.fireEvent(event.name, event);
1918                    }
1919                }
1920
1921                if (events.hasOwnProperty('gtm')) {
1922                    event = events.gtm;
1923                    if(Utils.isEventInTimeWindow(event.name,event,"dyn_gtm_"+eventId)) {
1924                        event = Utils.getFormFilledData(event);
1925                        GTM.fireEvent(event.name, event);
1926                    }
1927                }
1928
1929
1930            },
1931
1932            isFirstPurchaseFire: function ($eventName,orderId,pixel) {
1933
1934                if(Cookies.get("pys_"+$eventName+"_order_id_"+pixel) == orderId) {
1935                    return false;
1936                } else {
1937                    Cookies.set("pys_"+$eventName+"_order_id_"+pixel, orderId, { expires: 1,path: '/' });
1938                }
1939                return true;
1940            },
1941
1942            fireStaticEvents: function (pixel, timeout = 0) {
1943
1944                if (options.staticEvents.hasOwnProperty(pixel)) {
1945
1946                    $.each(options.staticEvents[pixel], function (eventId, events) {
1947
1948                        //skip purchase event if this order was fired
1949                        if( options.woo.hasOwnProperty('woo_purchase_on_transaction') &&
1950                            options.woo.woo_purchase_on_transaction &&
1951                            (eventId === "woo_purchase" || eventId === "woo_purchase_category") ) {
1952                            if(!Utils.isFirstPurchaseFire(eventId,events[0].woo_order,pixel)) {
1953                                return;
1954                            }
1955                        }
1956
1957                        if( options.edd.hasOwnProperty('edd_purchase_on_transaction') &&
1958                            options.edd.edd_purchase_on_transaction &&
1959                            (eventId === "edd_purchase" || eventId === "edd_purchase_category") ) {
1960                            if(!Utils.isFirstPurchaseFire(eventId,events[0].edd_order,pixel)) {
1961                                return;
1962                            }
1963                        }
1964
1965
1966                        $.each(events, function (index, event) {
1967
1968                            event.fired = event.fired || false;
1969
1970                            if (!event.fired && Utils.isEventInTimeWindow(event.name,event,'static_' + pixel+"_")) {
1971                                event = Utils.getFormFilledData(event);
1972
1973                                var fired = false;
1974
1975                                // fire event
1976                                if ( pixel === 'tiktok' ) {
1977                                    setTimeout(function() {
1978                                        getPixelBySlag(pixel).fireEvent(event.name, event);
1979                                    }, timeout * 500);
1980                                    timeout++;
1981                                } else {
1982                                    getPixelBySlag(pixel).fireEvent(event.name, event);
1983                                }
1984
1985                                // prevent event double event firing
1986                                event.fired = fired;
1987                            }
1988                        });
1989                    });
1990                }
1991            },
1992
1993            /**
1994             * Load tag's JS
1995             *
1996             * @link: https://developers.google.com/analytics/devguides/collection/gtagjs/
1997             * @link: https://developers.google.com/analytics/devguides/collection/gtagjs/custom-dims-mets
1998             */
1999            loadGoogleTag: function (id) {
2000
2001                if (!gtag_loaded) {
2002                    let dataLayerName = this.dataLayerName;
2003                    if(options.hasOwnProperty('GATags')){
2004                        switch (options.GATags.ga_datalayer_type) {
2005                            case 'default':
2006                                dataLayerName = 'dataLayerPYS';
2007                                break;
2008                            case 'custom':
2009                                dataLayerName = options.GATags.ga_datalayer_name;
2010                                break;
2011                            default:
2012                                dataLayerName = 'dataLayer';
2013                        }
2014                    }
2015                    this.dataLayerName = dataLayerName;
2016                    (function (window, document, src) {
2017                        var a = document.createElement('script'),
2018                            m = document.getElementsByTagName('script')[0];
2019                        a.async = 1;
2020                        a.src = src;
2021                        m.parentNode.insertBefore(a, m);
2022                    }
2022)(window, document, '//www.googletagmanager.com/gtag/js?id=' + id+'&l='+this.dataLayerName);
2023
2024                    window[dataLayerName] = window[dataLayerName] || [];
2025                    window.gtag = window.gtag || function gtag() {
2026                        window[dataLayerName].push(arguments);
2027                    };
2028
2029                    if ( options.google_consent_mode ) {
2030                        let data = {};
2031                        data[ 'analytics_storage' ] = options.gdpr.analytics_storage.enabled ? options.gdpr.analytics_storage.value : 'granted';
2032                        data[ 'ad_storage' ] = options.gdpr.ad_storage.enabled ? options.gdpr.ad_storage.value : 'granted';
2033                        data[ 'ad_user_data' ] = options.gdpr.ad_user_data.enabled ? options.gdpr.ad_user_data.value : 'granted';
2034                        data[ 'ad_personalization' ] = options.gdpr.ad_personalization.enabled ? options.gdpr.ad_personalization.value : 'granted';
2035
2036                        this.loadDefaultConsent( 'consent', 'default', data );
2037                    }
2038
2039                    gtag('js', new Date());
2040                    gtag_loaded = true;
2041
2042                }
2043
2044            },
2045
2046            loadDefaultConsent: function() {
2047                window[ this.dataLayerName ].push( arguments );
2048            },
2049
2050            loadGTMScript: function (id = '') {
2051                const domain = options.gtm.gtm_container_domain ?? 'www.googletagmanager.com';
2052                const loader = options.gtm.gtm_container_identifier ?? 'gtm';
2053                const gtm_auth = options.gtm.gtm_auth ?? ''; // Set this if needed
2054                const gtm_preview = options.gtm.gtm_preview ?? ''; // Set this if needed
2055                const datalayer_name = options.gtm.gtm_dataLayer_name ?? 'dataLayer';
2056
2057                window[ datalayer_name ] = window[ datalayer_name ] || [];
2058                window.gtag = window.gtag || function gtag() {
2059                    window[ datalayer_name ].push( arguments );
2060                };
2061
2062                if ( options.google_consent_mode ) {
2063                    let data = {};
2064                    data[ 'analytics_storage' ] = options.gdpr.analytics_storage.enabled ? options.gdpr.analytics_storage.value : 'granted';
2065                    data[ 'ad_storage' ] = options.gdpr.ad_storage.enabled ? options.gdpr.ad_storage.value : 'granted';
2066                    data[ 'ad_user_data' ] = options.gdpr.ad_user_data.enabled ? options.gdpr.ad_user_data.value : 'granted';
2067                    data[ 'ad_personalization' ] = options.gdpr.ad_personalization.enabled ? options.gdpr.ad_personalization.value : 'granted';
2068
2069                    this.GTMdataLayerName = datalayer_name;
2070                    this.loadDefaultGTMConsent( 'consent', 'default', data );
2071                }
2072
2073                (function(w, d, s, l, i) {
2074                    w[l] = w[l] || [];
2075                    w[l].push({ 'gtm.start': new Date().getTime(), event: 'gtm.js' });
2076                    const f = d.getElementsByTagName(s)[0];
2077                    const j = d.createElement(s);
2078                    const dl = l !== 'dataLayer' ? '&l=' + l : '';
2079                    j.async = true;
2080                    j.src = 'https://' + domain + '/' + loader + '.js?id=' + i + dl;
2081                    if (gtm_auth && gtm_preview) {
2082                        j.src += '&gtm_auth=' + gtm_auth + '&gtm_preview=' + gtm_preview + '&gtm_cookies_win=x';
2083                    }
2084                    f.parentNode.insertBefore(j, f);
2085                })(window, document, 'script', datalayer_name, id);
2086
2087            },
2088
2089            loadDefaultGTMConsent: function() {
2090                window[ this.GTMdataLayerName ].push( arguments );
2091            },
2092
2093            /**
2094             * GDPR
2095             */
2096
2097            loadPixels: function () {
2098
2099                if (options.gdpr.ajax_enabled && !options.gdpr.consent_magic_integration_enabled) {
2100
2101                    // retrieves actual PYS GDPR filters values which allow to avoid cache issues
2102                    $.get({
2103                        url: options.ajaxUrl,
2104                        dataType: 'json',
2105                        data: {
2106                            action: 'pys_get_gdpr_filters_values'
2107                        },
2108                        success: function (res) {
2109
2110                            if (res.success) {
2111
2112                                options.gdpr.all_disabled_by_api = res.data.all_disabled_by_api;
2113                                options.gdpr.facebook_disabled_by_api = res.data.facebook_disabled_by_api;
2114                                options.gdpr.tiktok_disabled_by_api = res.data.tiktok_disabled_by_api;
2115                                options.gdpr.analytics_disabled_by_api = res.data.analytics_disabled_by_api;
2116                                options.gdpr.google_ads_disabled_by_api = res.data.google_ads_disabled_by_api;
2117                                options.gdpr.pinterest_disabled_by_api = res.data.pinterest_disabled_by_api;
2118                                options.gdpr.bing_disabled_by_api = res.data.bing_disabled_by_api;
2119
2120                                options.cookie.externalID_disabled_by_api = res.data.externalID_disabled_by_api;
2121                                options.cookie.disabled_all_cookie = res.data.disabled_all_cookie;
2122                                options.cookie.disabled_advanced_form_data_cookie = res.data.disabled_advanced_form_data_cookie;
2123                                options.cookie.disabled_landing_page_cookie = res.data.disabled_landing_page_cookie || !options.enable_lading_page_param;
2124                                options.cookie.disabled_first_visit_cookie = res.data.disabled_first_visit_cookie;
2125                                options.cookie.disabled_trafficsource_cookie = res.data.disabled_trafficsource_cookie;
2126                                options.cookie.disabled_utmTerms_cookie = res.data.disabled_utmTerms_cookie;
2127                                options.cookie.disabled_utmId_cookie = res.data.disabled_utmId_cookie;
2128                            }
2129                            loadPixels();
2130
2131                        }
2132                    });
2133
2134                } else {
2135                    loadPixels();
2136                }
2137
2138            },
2139
2140            consentGiven: function (pixel) {
2141
2142                /**
2143                 * Cookiebot
2144                 */
2145                if (options.gdpr.cookiebot_integration_enabled && typeof Cookiebot !== 'undefined') {
2146
2147                    var cookiebot_consent_category = options.gdpr['cookiebot_' + pixel + '_consent_category'];
2148
2149                    if (options.gdpr[pixel + '_prior_consent_enabled']) {
2150                        if (Cookiebot.consented === true || Cookiebot.consent[cookiebot_consent_category]) {
2151                            return true;
2152                        }
2153                    } else {
2154                        if (Cookiebot.consent[cookiebot_consent_category]) {
2155                            return true;
2156                        }
2157                    }
2158                    return false;
2159
2160                }
2161
2162                /**
2163                 * Cookie Notice
2164                 */
2165                if (options.gdpr.cookie_notice_integration_enabled && typeof cnArgs !== 'undefined') {
2166
2167                    var cn_cookie = Cookies.get(cnArgs.cookieName);
2168
2169                    if (options.gdpr[pixel + '_prior_consent_enabled']) {
2170                        if (typeof cn_cookie === 'undefined' || cn_cookie === 'true') {
2171                            return true;
2172                        }
2173                    } else {
2174                        if (cn_cookie === 'true') {
2175                            return true;
2176                        }
2177                    }
2178
2179                    return false;
2180
2181                }
2182
2183                /**
2184                 * Cookie Law Info
2185                 */
2186
2187                if (options.gdpr.cookie_law_info_integration_enabled) {
2188                    var cli_cookie = Cookies.get('cookieyes-consent') ?? Cookies.get('wt_consent') ?? Cookies.get('viewed_cookie_policy');
2189                    if (options.gdpr[pixel + '_prior_consent_enabled']) {
2190                        if (typeof cli_cookie === 'undefined') return true;
2191                        if (
2192                            cli_cookie &&
2193                            (cli_cookie === Cookies.get('cookieyes-consent') || cli_cookie === Cookies.get('wt_consent'))
2194                        ) {
2195                            if (getCookieYes('analytics') === 'yes') {
2196                                return true;
2197                            }
2198                        } else if (cli_cookie && cli_cookie === Cookies.get('viewed_cookie_policy')) {
2199                            if (Cookies.get('viewed_cookie_policy') === 'yes') {
2200                                return true;
2201                            }
2202                        }
2203                    } else {
2204                        if (
2205                            cli_cookie &&
2206                            (cli_cookie === Cookies.get('cookieyes-consent') || cli_cookie === Cookies.get('wt_consent'))
2207                        ) {
2208                            if (getCookieYes('analytics') === 'yes') {
2209                                return true;
2210                            }
2211                        } else if (cli_cookie && cli_cookie === Cookies.get('viewed_cookie_policy')) {
2212                            if (Cookies.get('viewed_cookie_policy') === 'yes') {
2213                                return true;
2214                            }
2215                        }
2216                    }
2217                    return false;
2218                }
2219
2220                /**
2221                 * ConsentMagic
2222                 */
2223                if (options.gdpr.consent_magic_integration_enabled && typeof CS_Data !== "undefined" ) {
2224
2225                    let test_prefix = CS_Data.test_prefix;
2226                    if (
2227                        ( ( typeof CS_Data.cs_google_consent_mode_enabled !== "undefined" && CS_Data.cs_google_consent_mode_enabled == 1 ) && ( pixel == 'analytics' || pixel == 'google_ads' ) )
2228                        || ( typeof CS_Data.cs_meta_ldu_mode !== "undefined" && CS_Data.cs_meta_ldu_mode && pixel == 'facebook' )
2229                        || ( typeof CS_Data.cs_bing_consent_mode !== "undefined" && CS_Data.cs_bing_consent_mode.ad_storage.enabled && pixel == 'bing' )
2230                    ) {
2231                        if ( CS_Data.cs_cache_enabled == 0 || ( CS_Data.cs_cache_enabled == 1 && window.CS_Cache && window.CS_Cache.check_status ) ) {
2232                            return true;
2233                        } else {
2234                            return false;
2235                        }
2236                    }
2237
2238                    if( pixel == 'facebook' && ( CS_Data.cs_script_cat.facebook == 0 || CS_Data.cs_script_cat.facebook == CS_Data.cs_necessary_cat_id ) ) {
2239                        return true;
2240                    } else if( pixel == 'bing' && ( CS_Data.cs_script_cat.bing == 0 || CS_Data.cs_script_cat.bing == CS_Data.cs_necessary_cat_id ) ) {
2241                        return true;
2242                    } else if( pixel == 'analytics' && ( CS_Data.cs_script_cat.analytics == 0 || CS_Data.cs_script_cat.analytics == CS_Data.cs_necessary_cat_id ) ) {
2243                        return true;
2244                    } else if( pixel == 'google_ads' && ( CS_Data.cs_script_cat.gads == 0 || CS_Data.cs_script_cat.gads == CS_Data.cs_necessary_cat_id ) ) {
2245                        return true;
2246                    } else if( pixel == 'pinterest' && ( CS_Data.cs_script_cat.pinterest == 0 || CS_Data.cs_script_cat.pinterest == CS_Data.cs_necessary_cat_id ) ) {
2247                        return true;
2248                    } else if( pixel == 'tiktok' && ( CS_Data.cs_script_cat.tiktok == 0 || CS_Data.cs_script_cat.tiktok == CS_Data.cs_necessary_cat_id ) ) {
2249                        return true;
2250                    }
2251
2252                    let substring = "cs_enabled_cookie_term",
2253                        theCookies = document.cookie.split( ';' );
2254
2255                    for ( let i = 1; i <= theCookies.length; i++ ) {
2256                        if ( theCookies[ i - 1 ].indexOf( substring ) !== -1 ) {
2257                            let categoryCookie = theCookies[ i - 1 ].replace( 'cs_enabled_cookie_term' + test_prefix + '_', '' );
2258                            categoryCookie = Number( categoryCookie.replace( /\D+/g, "" ) );
2259                            let cs_cookie_val = Cookies.get( 'cs_enabled_cookie_term' + test_prefix + '_' + categoryCookie );
2260
2261                            if ( categoryCookie === CS_Data.cs_script_cat.facebook && pixel == 'facebook' ) {
2262                                return cs_cookie_val == 'yes';
2263                            } else if ( categoryCookie === CS_Data.cs_script_cat.bing && pixel == 'bing' ) {
2264                                return cs_cookie_val == 'yes';
2265                            } else if ( categoryCookie === CS_Data.cs_script_cat.analytics && pixel == 'analytics' ) {
2266                                return cs_cookie_val == 'yes';
2267                            } else if ( categoryCookie === CS_Data.cs_script_cat.gads && pixel == 'google_ads' ) {
2268                                return cs_cookie_val == 'yes';
2269                            } else if ( categoryCookie === CS_Data.cs_script_cat.pinterest && pixel == 'pinterest' ) {
2270                                return cs_cookie_val == 'yes';
2271                            } else if ( categoryCookie === CS_Data.cs_script_cat.tiktok && pixel == 'tiktok' ) {
2272                                return cs_cookie_val == 'yes';
2273                            }
2274                        }
2275                    }
2276
2277                    return false;
2278                }
2279
2280
2281                /**
2282                 * Real Cookie Banner
2283                 */
2284                if (options.gdpr.real_cookie_banner_integration_enabled) {
2285                    var consentApi = window.consentApi;
2286                    if (consentApi) {
2287                        switch (pixel) {
2288                            case "analytics":
2289                                return consentApi.consentSync("http", "_ga", "*").cookieOptIn;
2290                            case "facebook":
2291                                return consentApi.consentSync("http", "_fbp", "*").cookieOptIn;
2292                            case "pinterest":
2293                                return consentApi.consentSync("http", "_pinterest_sess", ".pinterest.com").cookieOptIn;
2294                            case "bing":
2295                                return consentApi.consentSync("http", "_uetsid", "*").cookieOptIn;
2296                            case "google_ads":
2297                                return consentApi.consentSync("http", "1P_JAR", ".google.com").cookieOptIn;
2298                            case 'tiktok':
2299                                return consentApi.consentSync("http", "tt_webid_v2", ".tiktok.com").cookieOptIn;
2300                            default:
2301                                return true;
2302                        }
2303                    }
2304                }
2305
2306                return true;
2307
2308            },
2309
2310            setupGdprCallbacks: function () {
2311
2312                let isConcent = false;
2313
2314                /**
2315                 * Cookiebot
2316                 */
2317                if ( options.gdpr.cookiebot_integration_enabled && typeof Cookiebot !== 'undefined' ) {
2318                    isConcent = true;
2319                    window.addEventListener( "CookiebotOnConsentReady", function () {
2320
2321                        let consent = {
2322                            facebook: true,
2323                            ga: true,
2324                            google_ads: true,
2325                            tiktok: true,
2326                            bing: true,
2327                            pinterest: true,
2328                            gtm: true,
2329                        };
2330                        Utils.initializeVideoAPIs( options );
2331
2332                        Utils.manageCookies();
2333                        if ( Cookiebot.consent.marketing ) {
2334                            Facebook.loadPixel();
2335      
2335                      Bing.loadPixel();
2336                            Pinterest.loadPixel();
2337                            GAds.loadPixel();
2338                            TikTok.loadPixel();
2339
2340                            consent.facebook = true;
2341                            consent.bing = true;
2342                            consent.google_ads = true;
2343                            consent.pinterest = true;
2344                            consent.tiktok = true;
2345                        }
2346                        if ( Cookiebot.consent.statistics ) {
2347                            Analytics.loadPixel();
2348
2349                            consent.ga = true;
2350                            consent.gtm = true;
2351                        }
2352                        if ( !Cookiebot.consent.marketing ) {
2353                            Facebook.disable();
2354                            Pinterest.disable();
2355                            Bing.disable()
2356                            GAds.disable();
2357                            TikTok.disable();
2358
2359                            consent.facebook = false;
2360                            consent.bing = false;
2361                            consent.google_ads = false;
2362                            consent.pinterest = false;
2363                            consent.tiktok = false;
2364                        }
2365                        if ( !Cookiebot.consent.statistics ) {
2366                            Analytics.disable();
2367
2368                            consent.ga = false;
2369                            consent.gtm = false;
2370                        }
2371
2372                        Utils.setupGDPRData( consent );
2373                    } );
2374                }
2375
2376                /**
2377                 * Cookie Notice
2378                 */
2379                if ( options.gdpr.cookie_notice_integration_enabled ) {
2380                    isConcent = true;
2381                    $( document ).onFirst( 'click', '.cn-set-cookie', function () {
2382
2383                        let consent = {};
2384
2385                        if ( $( this ).data( 'cookie-set' ) === 'accept' ) {
2386
2387                            Utils.initializeVideoAPIs( options );
2388
2389                            Facebook.loadPixel();
2390                            Analytics.loadPixel();
2391                            GAds.loadPixel();
2392                            Pinterest.loadPixel();
2393                            Bing.loadPixel();
2394                            TikTok.loadPixel();
2395
2396                            consent = {
2397                                facebook: true,
2398                                ga: true,
2399                                google_ads: true,
2400                                tiktok: true,
2401                                bing: true,
2402                                pinterest: true,
2403                                gtm: true,
2404                            };
2405                        } else {
2406                            Facebook.disable();
2407                            Analytics.disable();
2408                            GAds.disable();
2409                            Pinterest.disable();
2410                            Bing.disable();
2411                            TikTok.disable();
2412
2413                            consent = {
2414                                facebook: false,
2415                                ga: false,
2416                                google_ads: false,
2417                                tiktok: false,
2418                                bing: false,
2419                                pinterest: false,
2420                                gtm: false,
2421                            };
2422                        }
2423                        Utils.setupGDPRData( consent );
2424
2425                    } );
2426
2427                    $( document ).onFirst( 'click', '.cn-revoke-cookie', function () {
2428                        Facebook.disable();
2429                        Analytics.disable();
2430                        GAds.disable();
2431                        Pinterest.disable();
2432                        Bing.disable();
2433                        TikTok.disable();
2434
2435                        let consent = {
2436                            facebook: false,
2437                            ga: false,
2438                            google_ads: false,
2439                            tiktok: false,
2440                            bing: false,
2441                            pinterest: false,
2442                            gtm: false,
2443                        };
2444                        Utils.setupGDPRData( consent );
2445
2446                    } );
2447                }
2448
2449                /**
2450                 * Cookie Law Info
2451                 */
2452                if ( options.gdpr.cookie_law_info_integration_enabled ) {
2453                    isConcent = true;
2454                    $( document ).onFirst( 'click', '#wt-cli-accept-all-btn,#cookie_action_close_header, .cky-btn-accept', function () {
2455                        Utils.initializeVideoAPIs( options );
2456                        setTimeout( function () {
2457                            let cli_cookie = Cookies.get( 'cookieyes-consent' ) ?? Cookies.get( 'wt_consent' ) ?? Cookies.get( 'viewed_cookie_policy' );
2458                            if ( typeof cli_cookie !== 'undefined' ) {
2459                                if (
2460                                    cli_cookie &&
2461                                    (cli_cookie === Cookies.get('cookieyes-consent') || cli_cookie === Cookies.get('wt_consent'))
2462                                ) {
2463                                    if (getCookieYes('analytics') === 'yes') {
2464                                        Utils.manageCookies();
2465                                    }
2466                                } else if ( cli_cookie === Cookies.get( 'viewed_cookie_policy' ) && cli_cookie == 'yes' ) {
2467                                    Utils.manageCookies();
2468                                }
2469                            }
2470                        }, 1000 )
2471                        Facebook.loadPixel();
2472                        Analytics.loadPixel();
2473                        GAds.loadPixel();
2474                        Pinterest.loadPixel();
2475                        Bing.loadPixel();
2476                        TikTok.loadPixel();
2477
2478                        let consent = {
2479                            facebook: true,
2480                            ga: true,
2481                            google_ads: true,
2482                            tiktok: true,
2483                            bing: true,
2484                            pinterest: true,
2485                            gtm: true,
2486                        };
2487                        Utils.setupGDPRData( consent );
2488                    } );
2489
2490                    $( document ).onFirst( 'click', '#cookie_action_close_header_reject, .cky-btn-reject', function () {
2491                        Facebook.disable();
2492                        Analytics.disable();
2493                        GAds.disable();
2494                        Pinterest.disable();
2495                        Bing.disable();
2496                        TikTok.disable();
2497
2498                        let consent = {
2499                            facebook: false,
2500                            ga: false,
2501                            google_ads: false,
2502                            tiktok: false,
2503                            bing: false,
2504                            pinterest: false,
2505                            gtm: false,
2506                        };
2507                        Utils.setupGDPRData( consent );
2508                    } );
2509                }
2510
2511                /**
2512                 * ConsentMagic
2513                 */
2514                if ( options.gdpr.consent_magic_integration_enabled && typeof CS_Data !== "undefined" ) {
2515                    isConcent = true;
2516                    let test_prefix = CS_Data.test_prefix,
2517                        cs_refresh_after_consent = false,
2518                        substring = "cs_enabled_cookie_term";
2519
2520                    if ( CS_Data.cs_refresh_after_consent == 1 ) {
2521                        cs_refresh_after_consent = CS_Data.cs_refresh_after_consent;
2522                    }
2523
2524                    let consent_actions = function () {
2525                        let theCookies = document.cookie.split( ';' );
2526
2527                        let consent = {
2528                            facebook: true,
2529                            ga: true,
2530                            google_ads: true,
2531                            tiktok: true,
2532                            bing: true,
2533                            pinterest: true,
2534                            gtm: true,
2535                        };
2536
2537                        for ( let i = 1; i <= theCookies.length; i++ ) {
2538                            if ( theCookies[ i - 1 ].indexOf( substring ) !== -1 ) {
2539                                let categoryCookie = theCookies[ i - 1 ].replace( 'cs_enabled_cookie_term' + test_prefix + '_', '' );
2540                                categoryCookie = Number( categoryCookie.replace( /\D+/g, "" ) );
2541                                let cs_cookie_val = Cookies.get( 'cs_enabled_cookie_term' + test_prefix + '_' + categoryCookie );
2542                                if ( cs_cookie_val == 'yes' ) {
2543
2544                                    Utils.initializeVideoAPIs( options );
2545
2546                                    if ( ( categoryCookie === CS_Data.cs_script_cat.facebook ) || ( typeof CS_Data.cs_meta_ldu_mode !== "undefined" && CS_Data.cs_meta_ldu_mode ) ) {
2547                                        Facebook.loadPixel();
2548                                    }
2549
2550                                    if ( categoryCookie === CS_Data.cs_script_cat.bing || ( typeof CS_Data.cs_bing_consent_mode !== "undefined" && CS_Data.cs_bing_consent_mode.ad_storage.enabled ) ) {
2551                                        Bing.loadPixel();
2552                                    }
2553
2554                                    if ( categoryCookie === CS_Data.cs_script_cat.analytics || ( typeof CS_Data.cs_google_analytics_consent_mode !== "undefined" && CS_Data.cs_google_analytics_consent_mode == 1 ) ) {
2555                                        Analytics.loadPixel();
2556                                    }
2557                                    if ( categoryCookie === CS_Data.cs_script_cat.gads || ( typeof CS_Data.cs_google_ads_consent_mode !== "undefined" && CS_Data.cs_google_ads_consent_mode == 1 ) ) {
2558                                        GAds.loadPixel();
2559                                    }
2560
2561                                    if ( categoryCookie === CS_Data.cs_script_cat.pinterest ) {
2562                                        Pinterest.loadPixel();
2563                                    }
2564
2565                                    if ( categoryCookie === CS_Data.cs_script_cat.tiktok ) {
2566                                        TikTok.loadPixel();
2567                                    }
2568                                } else {
2569                                    if ( ( categoryCookie === CS_Data.cs_script_cat.facebook ) && ( typeof CS_Data.cs_meta_ldu_mode == "undefined" || !CS_Data.cs_meta_ldu_mode ) ) {
2570                                        Facebook.disable();
2571                                        consent.facebook = false;
2572                                    }
2573
2574                                    if ( categoryCookie === CS_Data.cs_script_cat.bing && ( typeof CS_Data.cs_bing_consent_mode == "undefined" || !CS_Data.cs_bing_consent_mode.ad_storage.enabled ) ) {
2575                                        Bing.disable();
2576                                        consent.bing = false;
2577                                    }
2578
2579                                    if ( categoryCookie === CS_Data.cs_script_cat.analytics && ( typeof CS_Data.cs_google_analytics_consent_mode == "undefined" || CS_Data.cs_google_analytics_consent_mode == 0 ) ) {
2580                                        Analytics.disable();
2581                                        consent.ga = false;
2582                                        consent.gtm = false;
2583                                    }
2584
2585                                    if ( categoryCookie === CS_Data.cs_script_cat.gads && ( typeof CS_Data.cs_google_ads_consent_mode == "undefined" || CS_Data.cs_google_ads_consent_mode == 0 ) ) {
2586                                        GAds.disable();
2587                                        consent.google_ads = false;
2588                                    }
2589
2590                                    if ( categoryCookie === CS_Data.cs_script_cat.pinterest ) {
2591                                        Pinterest.disable();
2592                                        consent.pinterest = false;
2593                                    }
2594
2595                                    if ( categoryCookie === CS_Data.cs_script_cat.tiktok ) {
2596                                        TikTok.disable();
2597                                        consent.tiktok = false;
2598                                    }
2599                                }
2600                                if ( Cookies.get( 'cs_enabled_advanced_matching' ) == 'yes' ) {
2601                                    Facebook.loadPixel();
2602                                }
2603                            }
2604                        }
2605
2606                        Utils.setupGDPRData( consent );
2607                    }
2608
2609                    if ( !cs_refresh_after_consent ) {
2610                        consent_actions();
2611
2612                        $( document ).on( 'click', '.cs_action_btn', function ( e ) {
2613                            e.preventDefault();
2614
2615                            let consent = {
2616                                facebook: true,
2617                                ga: true,
2618                                google_ads: true,
2619                                tiktok: true,
2620                                bing: true,
2621                                pinterest: true,
2622                                gtm: true,
2623                            };
2624
2625                            let elm = $( this ),
2626                                button_action = elm.attr( 'data-cs_action' );
2627
2628                            if ( button_action === 'allow_all' ) {
2629
2630                                Utils.initializeVideoAPIs( options );
2631
2632                                Facebook.loadPixel();
2633                                Bing.loadPixel();
2634                                Analytics.loadPixel();
2635                                GAds.loadPixel();
2636                                Pinterest.loadPixel();
2637                                TikTok.loadPixel();
2638
2639                                consent.facebook = true;
2640                                consent.bing = true;
2641                                consent.ga = true;
2642                                consent.google_ads = true;
2643                                consent.pinterest = true;
2644                                consent.tiktok = true;
2645                                consent.gtm = true;
2646
2647                                Utils.setupGDPRData( consent );
2648
2649                            } else if ( button_action === 'disable_all' ) {
2650
2651                                if (typeof CS_Data.cs_meta_ldu_mode == "undefined" || CS_Data.cs_meta_ldu_mode == 0 ) {
2652                                    Facebook.disable();
2653                                    consent.facebook = false;
2654                                }
2655
2656                                if (typeof CS_Data.cs_bing_consent_mode == "undefined" || CS_Data.cs_bing_consent_mode.ad_storage.enabled == 0 ) {
2657                                    Bing.disable();
2658                                    consent.bing = false;
2659                                }
2660
2661                                if ( typeof CS_Data.cs_google_analytics_consent_mode == "undefined" || CS_Data.cs_google_analytics_consent_mode == 0 ) {
2662                                    Analytics.disable();
2663                                    consent.ga = false;
2664                                    consent.gtm = false;
2665                                }
2666
2667                                if ( typeof CS_Data.cs_google_ads_consent_mode == "undefined" || CS_Data.cs_google_ads_consent_mode == 0 ) {
2668                                    GAds.disable();
2669                                    consent.google_ads = false;
2670                                }
2671                                Pinterest.disable();
2672                                TikTok.disable();
2673
2674                                consent.pinterest = false;
2675                                consent.tiktok = false;
2676
2677                                Utils.setupGDPRData( consent );
2678                            } else if ( button_action === 'cs_confirm' ) {
2679                                consent_actions();
2680                            }
2681                        } );
2682                    }
2683                }
2684
2685                /**
2686                 * Real Cookie Banner
2687                 */
2688                if ( options.gdpr.real_cookie_banner_integration_enabled ) {
2689                    isConcent = true;
2690                    let consentApi = window.consentApi;
2691                    if ( consentApi ) {
2692                        consentApi.consent( "http", "_ga", "*" )
2693                            .then( Analytics.loadPixel.bind( Analytics ), Analytics.disable.bind( Analytics ) );
2694                        consentApi.consent( "http", "1P_JAR", ".google.com" )
2695                            .then( GAds.loadPixel.bind( GAds ), GAds.disable.bind( GAds ) );
2696                        consentApi.consent( "http", "_fbp", "*" )
2697                            .then( Facebook.loadPixel.bind( Facebook ), Facebook.disable.bind( Facebook ) );
2698                        consentApi.consent( "http", "_pinterest_sess", ".pinterest.com" )
2699                            .then( Pinterest.loadPixel.bind( Pinterest ), Pinterest.disable.bind( Pinterest ) );
2700                        consentApi.consent( "http", "_uetsid", "*" )
2701                            .then( Bing.loadPixel.bind( Bing ), Bing.disable.bind( Bing ) );
2702                        consentApi.consent( "http", "tt_webid_v2", ".tiktok.com" )
2703                            .then( TikTok.loadPixel.bind( TikTok ), TikTok.disable.bind( TikTok ) );
2704
2705                        let consent = {
2706                            facebook: true,
2707                            ga: true,
2708                            google_ads: true,
2709                            tiktok: true,
2710                            bing: true,
2711                            pinterest: true,
2712                            gtm: true,
2713                        };
2714
2715                        if (!consentApi.consentSync("http", "_ga", "*").cookieOptIn) {
2716                            consent.ga = false;
2717                            consent.gtm = false;
2718                        }
2719                        if (!consentApi.consentSync("http", "_fbp", "*").cookieOptIn) {
2720                            consent.facebook = false;
2721                        }
2722                        if (!consentApi.consentSync("http", "_pinterest_sess", ".pinterest.com").cookieOptIn) {
2723                            consent.pinterest = false;
2724                        }
2725                        if (!consentApi.consentSync("http", "_uetsid", "*").cookieOptIn) {
2726                            consent.bing = false;
2727                        }
2728                        if (!consentApi.consentSync("http", "1P_JAR", ".google.com").cookieOptIn) {
2729                            consent.google_ads = false;
2730                        }
2731                        if (!consentApi.consentSync("http", "tt_webid_v2", ".tiktok.com").cookieOptIn) {
2732                            consent.tiktok = false;
2733                        }
2734                        Utils.setupGDPRData( consent );
2735
2736                        // load WatchVideo event APIs for Auto
2737                        /**
2738                         * Real Cookie Banner.
2739                         */
2740                        if ( options.hasOwnProperty( 'automatic' ) && options.automatic.enable_video && options.automatic.enable_youtube ) {
2741                            consentApi.consent( "http", "CONSENT", ".youtube.com" ).then( Utils.initYouTubeAPI );
2742                        }
2743
2744                        if ( options.hasOwnProperty( 'automatic' ) && options.automatic.enable_video && options.automatic.enable_vimeo ) {
2745                            consentApi.consent( "http"
2745, "player", ".vimeo.com" ).then( Utils.initVimeoAPI );
2746                        }
2747                    }
2748                }
2749
2750                if ( !isConcent ) {
2751                    Utils.initializeVideoAPIs( options );
2752                }
2753            },
2754
2755            setupGDPRData: function ( consent ) {
2756                consent = window.btoa( JSON.stringify( consent ) );
2757                Cookies.set( 'pys_consent', consent, { expires: 365, path: '/', domain: domain } );
2758            },
2759
2760            /**
2761             * Enrich
2762             */
2763            isCheckoutPage: function () {
2764                return $('body').hasClass('woocommerce-checkout') || document.querySelector('.woocommerce-checkout') ||
2765                    $('body').hasClass('edd-checkout');
2766            },
2767            addCheckoutFields : function() {
2768                var utm = "";
2769                var utms = getUTMs()
2770                $.each(utmTerms, function (index, name) {
2771                    if(index > 0) {
2772                        utm+="|";
2773                    }
2774                    utm+=name+":"+utms[name];
2775                });
2776                var utmIdList = "";
2777                var utmsIds = getUTMId()
2778                $.each(utmId, function (index, name) {
2779                    if(index > 0) {
2780                        utmIdList+="|";
2781                    }
2782                    utmIdList+=name+":"+utmsIds[name];
2783                });
2784                var utmIdListLast = "";
2785                var utmsIdsLast = getUTMId(true)
2786                $.each(utmId, function (index, name) {
2787                    if(index > 0) {
2788                        utmIdListLast+="|";
2789                    }
2790                    utmIdListLast+=name+":"+utmsIdsLast[name];
2791                });
2792
2793
2794                var utmLast = "";
2795                var utmsLast = getUTMs(true)
2796                $.each(utmTerms, function (index, name) {
2797                    if(index > 0) {
2798                        utmLast+="|";
2799                    }
2800                    utmLast+=name+":"+utmsLast[name];
2801                });
2802
2803                var dateTime = getDateTime();
2804                var landing = Cookies.get('pys_landing_page');
2805                var lastLanding = Cookies.get('last_pys_landing_page');
2806                var trafic = Cookies.get('pysTrafficSource');
2807                var lastTrafic = Cookies.get('last_pysTrafficSource');
2808
2809                var $form = null;
2810                if($('body').hasClass('woocommerce-checkout')) {
2811                    $form = $("form.woocommerce-checkout");
2812                } else {
2813                    $form = $("#edd_purchase_form");
2814                }
2815                var inputs = {'pys_utm':utm,
2816                    'pys_utm_id':utmIdList,
2817                    'pys_browser_time':dateTime.join("|"),
2818                    'pys_landing':landing,
2819                    'pys_source':trafic,
2820                    'pys_order_type': $(".wcf-optin-form").length > 0 ? "wcf-optin" : "normal",
2821
2822                    'last_pys_landing':lastLanding,
2823                    'last_pys_source':lastTrafic,
2824                    'last_pys_utm':utmLast,
2825                    'last_pys_utm_id':utmIdListLast,
2826                }
2827
2828                Object.keys(inputs).forEach(function(key,index) {
2829                    $form.append("<input type='hidden' name='"+key+"' value='"+inputs[key]+"' /> ");
2830                });
2831
2832
2833            },
2834
2835            /**
2836             * Advanced From Data
2837             */
2838            saveAdvancedFormData: function ( email, phone, firstName, lastName, override = true ) {
2839
2840                if ( !options.cookie.disabled_advanced_form_data_cookie ) {
2841                    let data = Utils.getAdvancedFormData();
2842                    // Ensure data["address"] is an object
2843
2844                    if ( email != null ) {
2845                        if ( !override ) {
2846                            if ( typeof data[ "email" ] === 'undefined' || !data[ "email" ] ) {
2847                                data[ "email" ] = email;
2848                            }
2849                        } else {
2850                            data[ "email" ] = email;
2851                        }
2852
2853                        if ( typeof data[ "emails" ] === 'object' ) {
2854                            if ( override ) {
2855                                data[ "emails" ] = [ email, ...Object.values( data[ "emails" ] ) ];
2856                            } else {
2857                                data[ "emails" ] = [ ...Object.values( data[ "emails" ] ), email ];
2858                            }
2859                        } else {
2860                            data[ "emails" ] = [ email ];
2861                        }
2862                        data[ "emails" ] = [ ...new Set( data[ "emails" ] ) ];
2863                        data[ "emails" ] = data[ "emails" ].slice( 0, 3 );
2864                    }
2865
2866                    if ( phone != null ) {
2867                        if ( !override ) {
2868                            if ( typeof data[ "phone" ] === 'undefined' || !data[ "phone" ] ) {
2869                                data[ "phone" ] = phone;
2870                            }
2871                        } else {
2872                            data[ "phone" ] = phone;
2873                        }
2874
2875                        if ( typeof data[ "phones" ] === 'object' ) {
2876                            if ( override ) {
2877                                data[ "phones" ] = [ phone, ...Object.values( data[ "phones" ] ) ];
2878                            } else {
2879                                data[ "phones" ] = [ ...Object.values( data[ "phones" ] ), phone ];
2880                            }
2881                        } else {
2882                            data[ "phones" ] = [ phone ];
2883                        }
2884                        data[ "phones" ] = [ ...new Set( data[ "phones" ] ) ];
2885                        data[ "phones" ] = data[ "phones" ].slice( 0, 3 );
2886                    }
2887
2888                    if ( firstName != null ) {
2889                        if ( !override ) {
2890                            if ( typeof data[ "first_name" ] === 'undefined' || !data[ "first_name" ] ) {
2891                                data[ "first_name" ] = firstName;
2892                            }
2893                        } else {
2894                            data[ "first_name" ] = firstName;
2895                        }
2896
2897                        if ( typeof data[ "fns" ] === 'object' ) {
2898                            if ( override ) {
2899                                data[ "fns" ] = [ firstName, ...Object.values( data[ "fns" ] ) ];
2900                            } else {
2901                                data[ "fns" ] = [ ...Object.values( data[ "fns" ] ), firstName ];
2902                            }
2903                        } else {
2904                            data[ "fns" ] = [ firstName ];
2905                        }
2906                        data[ "fns" ] = [ ...new Set( data[ "fns" ] ) ];
2907                        data[ "fns" ] = data[ "fns" ].slice( 0, 2 );
2908                    }
2909
2910                    if ( lastName != null ) {
2911                        if ( !override ) {
2912                            if ( typeof data[ "last_name" ] === 'undefined' || !data[ "last_name" ] ) {
2913                                data[ "last_name" ] = lastName;
2914                            }
2915                        } else {
2916                            data[ "last_name" ] = lastName;
2917                        }
2918
2919                        if ( typeof data[ "lns" ] === 'object' ) {
2920                            if ( override ) {
2921                                data[ "lns" ] = [ lastName, ...Object.values( data[ "lns" ] ) ];
2922                            } else {
2923                                data[ "lns" ] = [ ...Object.values( data[ "fns" ] ), lastName ];
2924                            }
2925                        } else {
2926                            data[ "lns" ] = [ lastName ];
2927                        }
2928                        data[ "lns" ] = [ ...new Set( data[ "lns" ] ) ];
2929                        data[ "lns" ] = data[ "lns" ].slice( 0, 2 );
2930                    }
2931
2932                    Cookies.set( 'pys_advanced_form_data', JSON.stringify( data ), { expires: 300,path: '/',domain: domain } );
2933                } else {
2934                    Cookies.remove( 'pys_advanced_form_data', { path: '/',domain: domain } )
2935                }
2936                if(GTM.isEnabled()){
2937                    GTM.updateEnhancedConversionData();
2938                }
2939                if(Analytics.isEnabled()){
2940                    Analytics.updateEnhancedConversionData();
2941                } else if ( GAds.isEnabled() ) {
2942                    GAds.updateEnhancedConversionData();
2943                }
2944            },
2945            getAdvancedMergeFormData: function (allways_provided_data = false) {
2946                const advanced = Utils.getAdvancedFormData();
2947                let mergedData = {},
2948                    limit = options.tracking_analytics.use_multiple_provided_data || allways_provided_data ? 3 : 1,
2949                    address_limit = options.tracking_analytics.use_multiple_provided_data || allways_provided_data ? 2 : 1;
2950
2951                if ( options.tracking_analytics.use_encoding_provided_data || allways_provided_data) {
2952                    mergedData.sha256_email_address = [];
2953                    mergedData.sha256_phone_number = [];
2954                    mergedData.address = [];
2955                    if ( options.tracking_analytics.hasOwnProperty( "userData" ) ) {
2956                        if ( options.tracking_analytics.userData.hasOwnProperty( "emails" ) && Object.keys( options.tracking_analytics.userData.emails ).length > 0 ) {
2957                            Object.keys( options.tracking_analytics.userData.emails ).forEach( ( key ) => {
2958                                mergedData.sha256_email_address.push( sha256( options.tracking_analytics.userData.emails[ key ] ) );
2959                            } )
2960                        }
2961                        if ( options.tracking_analytics.userData.hasOwnProperty( "phones" ) && Object.keys( options.tracking_analytics.userData.phones ).length > 0 ) {
2962                            Object.keys( options.tracking_analytics.userData.phones ).forEach( ( key ) => {
2963                                mergedData.sha256_phone_number.push( sha256( options.tracking_analytics.userData.phones[ key ] ) );
2964                            } )
2965                        }
2966                        if ( options.tracking_analytics.userData.hasOwnProperty( "addresses" ) && Object.keys( options.tracking_analytics.userData.addresses ).length > 0 ) {
2967                            Object.keys( options.tracking_analytics.userData.addresses ).forEach( ( key ) => {
2968                                let address = Object.assign( {}, options.tracking_analytics.userData.addresses[ key ] );
2969
2970                                if ( address.first_name ) {
2971                                    address.sha256_first_name = address.first_name !== '' ? sha256( address.first_name ) : '';
2972                                    delete address.first_name;
2973                                }
2974                                if ( address.last_name ) {
2975                                    address.sha256_last_name = address.last_name !== '' ? sha256( address.last_name ) : '';
2976                                    delete address.last_name;
2977                                }
2978                                mergedData.address.push( address );
2979                            } )
2980                        }
2981                    }
2982
2983                    let data_persistency = options.data_persistency;
2984
2985                    //emails
2986                    if ( advanced.emails && Object.keys( advanced.emails ).length > 0 ) {
2987                        Object.keys( advanced.emails ).forEach( ( ke
2987y ) => {
2988                            if ( data_persistency === 'recent_data' ) {
2989                                mergedData.sha256_email_address.push( sha256( advanced.emails[ key ] ) );
2990                            } else {
2991                                mergedData.sha256_email_address.unshift( sha256( advanced.emails[ key ] ) );
2992                            }
2993                        } )
2994                    }
2995                    if ( advanced.email && advanced.email !== '' ) {
2996                        if ( data_persistency === 'recent_data' ) {
2997                            mergedData.sha256_email_address.push( sha256( advanced.email ) );
2998                        } else {
2999                            mergedData.sha256_email_address.unshift( sha256( advanced.email ) );
3000                        }
3001                    }
3002                    mergedData.sha256_email_address = [ ...new Set( mergedData.sha256_email_address ) ];
3003                    mergedData.sha256_email_address = mergedData.sha256_email_address.slice( 0, limit );
3004
3005                    //phones
3006                    if ( advanced.phones && Object.keys( advanced.phones ).length > 0 ) {
3007                        Object.keys( advanced.phones ).forEach( ( key ) => {
3008                            if ( data_persistency === 'recent_data' ) {
3009                                mergedData.sha256_phone_number.push( sha256( advanced.phones[ key ] ) );
3010                            } else {
3011                                mergedData.sha256_phone_number.unshift( sha256( advanced.phones[ key ] ) );
3012                            }
3013                        } )
3014                    }
3015                    if ( advanced.phone && advanced.phone !== '' ) {
3016                        if ( data_persistency === 'recent_data' ) {
3017                            mergedData.sha256_phone_number.push( sha256( advanced.phone ) );
3018                        } else {
3019                            mergedData.sha256_phone_number.unshift( sha256( advanced.phone ) );
3020                        }
3021                    }
3022                    mergedData.sha256_phone_number = [ ...new Set( mergedData.sha256_phone_number ) ];
3023                    mergedData.sha256_phone_number = mergedData.sha256_phone_number.slice( 0, limit );
3024
3025                    //first and last names
3026                    if ( advanced.fns && Object.keys( advanced.fns ).length > 0 ) {
3027                        Object.entries( advanced.fns ).forEach( ( item ) => {
3028                            if ( mergedData.address.length < address_limit ) {
3029                                let first_name = item[ 1 ];
3030                                let last_name = ( advanced.lns && Object.keys( advanced.lns ).length > 0 ) ? ( advanced.lns[ item[ 0 ] ] ? advanced.lns[ item[ 0 ] ] : advanced.lns[ 0 ] ) : '';
3031                                let address = {
3032                                    sha256_first_name: first_name !== '' ? sha256( first_name ) : '',
3033                                    sha256_last_name: last_name !== '' ? sha256( last_name ) : '',
3034                                    // Add other address properties here if they exist in advanced
3035                                };
3036                                mergedData.address.push( address );
3037                            }
3038                        } )
3039                    }
3040
3041                    if ( advanced.first_name || advanced.last_name ) {
3042                        if ( mergedData.address.length < address_limit ) {
3043                            let address = {
3044                                sha256_first_name: advanced.first_name !== '' ? sha256( advanced.first_name ) : '',
3045                                sha256_last_name: advanced.last_name !== '' ? sha256( advanced.last_name ) : '',
3046                                // Add other address properties here if they exist in advanced
3047                            };
3048                            mergedData.address.push( address );
3049                        }
3050                    }
3051                } else {
3052                    mergedData.email = [];
3053                    mergedData.phone_number = [];
3054                    mergedData.address = [];
3055                    if ( options.tracking_analytics.hasOwnProperty( "userData" ) ) {
3056                        if ( options.tracking_analytics.userData.hasOwnProperty( "emails" ) && Object.keys( options.tracking_analytics.userData.emails ).length > 0 ) {
3057                            Object.keys( options.tracking_analytics.userData.emails ).forEach( ( ke
3057y ) => {
3058                                mergedData.email.push( options.tracking_analytics.userData.emails[ key ] );
3059                            } )
3060                        }
3061                        if ( options.tracking_analytics.userData.hasOwnProperty( "phones" ) && Object.keys( options.tracking_analytics.userData.phones ).length > 0 ) {
3062                            Object.keys( options.tracking_analytics.userData.phones ).forEach( ( key ) => {
3063                                mergedData.phone_number.push( options.tracking_analytics.userData.phones[ key ] );
3064                            } )
3065                        }
3066                        if ( options.tracking_analytics.userData.hasOwnProperty( "addresses" ) && Object.keys( options.tracking_analytics.userData.addresses ).length > 0 ) {
3067                            Object.keys( options.tracking_analytics.userData.addresses ).forEach( ( key ) => {
3068                                mergedData.address.push( options.tracking_analytics.userData.addresses[ key ] );
3069                            } )
3070                        }
3071                    }
3072
3073                    let data_persistency = options.data_persistency;
3074
3075                    //emails
3076                    if ( advanced.emails && Object.keys( advanced.emails ).length > 0 ) {
3077                        Object.keys( advanced.emails ).forEach( ( key ) => {
3078                            if ( data_persistency === 'recent_data' ) {
3079                                mergedData.email.push( advanced.emails[ key ] );
3080                            } else {
3081                                mergedData.email.unshift( advanced.emails[ key ] );
3082                            }
3083                        } )
3084                    }
3085                    if ( advanced.email && advanced.email !== '' ) {
3086                        if ( data_persistency === 'recent_data' ) {
3087                            mergedData.email.push( advanced.email );
3088                        } else {
3089                            mergedData.email.unshift( advanced.email );
3090                        }
3091                    }
3092                    mergedData.email = [ ...new Set( mergedData.email ) ];
3093                    mergedData.email = mergedData.email.slice( 0, limit );
3094
3095                    //phones
3096                    if ( advanced.phones && Object.keys( advanced.phones ).length > 0 ) {
3097                        Object.keys( advanced.phones ).forEach( ( key ) => {
3098                            if ( data_persistency === 'recent_data' ) {
3099                                mergedData.phone_number.push( advanced.phones[ key ] );
3100                            } else {
3101                                mergedData.phone_number.unshift( advanced.phones[ key ] );
3102                            }
3103                        } )
3104                    }
3105                    if ( advanced.phone && advanced.phone !== '' ) {
3106                        if ( data_persistency === 'recent_data' ) {
3107                            mergedData.phone_number.push( advanced.phone );
3108                        } else {
3109                            mergedData.phone_number.unshift( advanced.phone );
3110                        }
3111                    }
3112                    mergedData.phone_number = [ ...new Set( mergedData.phone_number ) ];
3113                    mergedData.phone_number = mergedData.phone_number.slice( 0, limit );
3114
3115                    //first and last names
3116                    if ( advanced.fns && Object.keys( advanced.fns ).length > 0 ) {
3117                        Object.entries( advanced.fns ).forEach( ( item ) => {
3118                            if ( mergedData.address.length < address_limit ) {
3119                                let first_name = item[ 1 ];
3120                                let last_name = ( advanced.lns && Object.keys( advanced.lns ).length > 0 ) ? ( advanced.lns[ item[ 0 ] ] ? advanced.lns[ item[ 0 ] ] : advanced.lns[ 0 ] ) : '';
3121                                let address = {
3122                                    first_name: first_name || '',
3123                                    last_name: last_name || '',
3124                                    // Add other address properties here if they exist in advanced
3125                                };
3126                                mergedData.address.push( address );
3127                            }
3128                        } )
3129                    }
3130
3131                    if ( advanced.first_name || advanced.last_name ) {
3132                        if ( mergedData.address.length < address_limit ) {
3133                            let address = {
3134                                first_name: advanced.first_name || '',
3135                                last_name: advanced.last_name || '',
3136                                // Add other address properties here if they exist in advanced
3137                            };
3138                            mergedData.address.push( address );
3139                        }
3140                    }
3141                }
3142
3143                Utils.removeEmptyProperties( mergedData );
3144                return mergedData;
3145            },
3146            removeEmptyProperties : function(obj) {
3147
3148                if (obj.hasOwnProperty('address')) {
3149                    // Проходим по каждому массиву в 'address'
3150                    for (let i = 0; i < obj['address'].length; i++) {
3151                        let address1 = obj['address'][i];
3152
3153                        // Сравниваем с каждым другим массивом в 'address'
3154                        for (let j = i + 1; j < obj['address'].length; j++) {
3155                            let address2 = obj['address'][j];
3156
3157                            // Если находим дублирующиеся свойства, удаляем их из address2
3158                            for (let prop in address1) {
3159                                if (address1[prop] === address2[prop]) {
3160                                    delete address2[prop];
3161                                }
3162                            }
3163                        }
3164                    }
3165                }
3166
3167                for (let key in obj) {
3168                    if (obj[key] === null || obj[key] === undefined || obj[key] === '') {
3169                        delete obj[key];
3170                    } else if (Array.isArray(obj[key])) {
3171                        obj[key] = [...new Set(obj[key])]; // Удаление дубликатов из массива
3172                        obj[key] = obj[key].filter(item => item !== null && item !== undefined && item !== '');
3173                        // Обработка объектов внутри массивов
3174                        obj[key] = obj[key].map(item => {
3175                            if (item === null) {
3176                                return; // Пропускаем null элементы
3177                            } else if (Array.isArray(item)) {
3178                                return this.removeEmptyProperties(item);
3179                            } else if (typeof item === 'object') {
3180                                let cleanedItem = this.removeEmptyProperties(item);
3181                                if (Object.keys(cleanedItem).length > 0) {
3182                                    return cleanedItem;
3183                                }
3184                            } else {
3185                                return item;
3186                            }
3187                        });
3188                        // Удаляем пустые объекты и null из массива
3189                        obj[key] = obj[key].filter(item => item !== undefined && !(typeof item === 'object' && Object.keys(item).length === 0));
3190                        if (obj[key].length === 0) {
3191                            delete obj[key];
3192                        }
3193                    } else if (typeof obj[key] === 'object') {
3194                        this.removeEmptyProperties(obj[key]);
3195                        if (Object.keys(obj[key]).length === 0) {
3196                            delete obj[key];
3197                        }
3198                    }
3199                }
3200                return obj;
3201            },
3202            getAdvancedFormData: function () {
3203                let dataStr = Cookies.get("pys_advanced_form_data");
3204                if(dataStr === undefined) {
3205                    return {'first_name':"",'last_name':"",'email':"",'phone':"",'fns':[],'lns':[],'emails':[],'phones':[]};
3206                } else {
3207                    return JSON.parse(dataStr);
3208                }
3209            },
3210
3211            getFormFilledData: function ( event ) {
3212                if ( Object.keys(options.track_dynamic_fields).length > 0 && Object.keys(event.params).length > 0 ) {
3213                    Object.entries(event.params).forEach((item) => {
3214
3215                        if ( options.track_dynamic_fields.hasOwnProperty(item[0]) ) {
3216                            let fieldData = Cookies.get('pys_dyn_field_' + item[1] );
3217
3218                            if(fieldData !== undefined && fieldData !== '') {
3219                                event.params[item[0]] = fieldData;
3220                            } else {
3221                                delete event.params[item[0]];
3222                            }
3223                        }
3224                    })
3225                }
3226                return event;
3227            }
3228
3229        };
3230
3231    }(options);
3232
3233    var TikTok = function (options) {
3234
3235        var initialized = false;
3236
3237        function fireEvent(name, event) {
3238
3239            if(typeof window.pys_event_data_filter === "function" && window.pys_disable_event_filter(name,'tiktok')) {
3240                return;
3241            }
3242
3243            var data = event.params;
3244
3245            var ids = event.pixelIds.filter(function (pixelId) {
3246                return !Utils.hideMatchingPixel(pixelId, 'tiktok');
3247            })
3248            var params = {};
3249            Utils.copyProperties(data, params);
3250
3251            params.eventID = Utils.generateUniqueId(event);
3252
3253            if(ids.length > 0){
3254                TikTok.fireEventAPI(name, event, params);
3255            }
3256            ids.forEach(function(pixelId){
3257                if (options.debug) {
3258                    console.log('[TikTok] ' + name, params,"pixel_id",pixelId);
3259                }
3260
3261                ttq.instance(pixelId).track(name,params)
3262
3263            });
3264
3265            var customEvent = new CustomEvent('tiktok_event_sent', {
3266                detail: {
3267                    eventName: name,
3268                    params: params,
3269                    pixel_ids: ids
3270                }
3271            });
3272            window.dispatchEvent(customEvent);
3273        }
3274
3275        return {
3276            tag: function() {
3277                return "tiktok";
3278            },
3279            isEnabled: function () {
3280                return options.hasOwnProperty('tiktok');
3281            },
3282            getHidePixel: function(){
3283                if(this.isEnabled() && options.tiktok.hasOwnProperty('hide_pixels'))
3284                {
3285                    return options.tiktok.hide_pixels;
3286                }
3287                return [];
3288            },
3289            disable: function () {
3290                initialized = false;
3291            },
3292
3293            loadPixel:function () {
3294                if (initialized || !this.isEnabled() || !Utils.consentGiven('tiktok')) {
3295                    return;
3296                }
3297                for (var i = 0; i < options.tiktok.pixelIds.length; i++) {
3298                    var trackingId = options.tiktok.pixelIds[i];
3299                    if (!Utils.hideMatchingPixel(trackingId, 'tiktok')) {
3300                        !function (w, d, t) {
3301                            w.TiktokAnalyticsObject=t;
3302                            var ttq=w[t]=w[t]||[];
3303                            ttq.methods=["page","track","identify","instances","debug","on","off","once","ready","alias","group","enableCookie","disableCookie"];
3304                            ttq.setAndDefer=function(t,e){t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}};
3305                            for(var i=0;i<ttq.methods.length;i++)
3306                                ttq.setAndDefer(ttq,ttq.methods[i]);
3307                            ttq.instance=function(t){for(var e=ttq._i[t]||[],n=0;n<ttq.methods.length;n++)ttq.setAndDefer(e,ttq.methods[n]);return e};
3308                            ttq.load=function(e,n){var i="https://analytics.tiktok.com/i18n/pixel/events.js";ttq._i=ttq._i||{},ttq._i[e]=[],ttq._i[e]._u=i,ttq._t=ttq._t||{},ttq._t[e]=+new Date,ttq._o=ttq._o||{},ttq._o[e]=n||{};var o=document.createElement("script");o.type="text/javascript",o.async=!0,o.src=i+"?sdkid="+e+"&lib="+t;var a=document.getElementsByTagName("script")[0];a.parentNode.insertBefore(o,a)};
3309
3310                            //ttq.load('C60QSCQRVDG9JAKNPK2G');
3311                            //ttq.page();
3312                        }(window, document, 'ttq');
3313                        break;
3314                    }
3315                }
3316
3317
3318                var ids = options.tiktok.pixelIds.filter(function (pixelId) {
3319                    return !Utils.hideMatchingPixel(pixelId, 'tiktok');
3320                })
3321                ids.forEach(function (pixelId) {
3322
3323                    ttq.load(pixelId);
3324                    ttq.page();
3325                    let advancedMatching = {};
3326                    if(options.tiktok.hasOwnProperty('advanced_matching')
3327                        && Object.keys(options.tiktok.advanced_matching).length > 0) {
3328                        advancedMatching = options.tiktok.advanced_matching;
3329                        if(!advancedMatching.hasOwnProperty("external_id")){
3330                            if (Cookies.get('pbid')) {
3331                                advancedMatching["external_id"] = Cookies.get('pbid');
3332                            }
3333                        }
3334                        else if(advancedMatching.hasOwnProperty("external_id") && advancedMatching.external_id != Cookies.get('pbid'))
3335                        {
3336                            advancedMatching["external_id"] = Cookies.get('pbid') ? Cookies.get('pbid') : advancedMatching.external_id;
3337                        }
3338
3339                        ttq.instance(pixelId).identify(advancedMatching)
3340                    }
3341                });
3342                initialized = true;
3343
3344                if (options.staticEvents.hasOwnProperty('tiktok')) {
3345                    var timeout = 1;
3346                    setTimeout(function (timeout) {
3347                        Utils.fireStaticEvents('tiktok', timeout);
3348                    }, 1500, timeout)
3349                }
3350            },
3351
3352            fireEvent: function (name, data) {
3353                if (!initialized || !this.isEnabled()) {
3354                    return false;
3355                }
3356                data.delay = data.delay || 0;
3357
3358                if (data.delay === 0) {
3359                    fireEvent(name, data);
3360                } else {
3361                    setTimeout(function (name, params) {
3362                        fireEvent(name, params);
3363                    }, data.delay * 1000, name, data);
3364                }
3365                return true;
3366            },
3367
3368            fireEventAPI: function (name, event, params) {
3369
3370                var ids = event.pixelIds.filter(function (pixelId) {
3371                    return !Utils.hideMatchingPixel(pixelId, 'tiktok');
3372                })
3373                var notCachedEventsIds = new Array();
3374                var isAddToCartFromJs =  options.woo.hasOwnProperty("addToCartCatchMethod")
3375                    && options.woo.addToCartCatchMethod === "add_cart_js";
3376                if(!isAddToCartFromJs) {
3377                    notCachedEventsIds.push('woo_add_to_cart_on_button_click')
3378                }
3379
3380                if(options.tiktok.serverApiEnabled) {
3381                    if(!notCachedEventsIds.includes(event.e_id)) {
3382
3383                        var isApiDisabled = options.gdpr.all_disabled_by_api ||
3384                            options.gdpr.tiktok_disabled_by_api ||
3385                            options.gdpr.cookiebot_integration_enabled ||
3386                            options.gdpr.cookie_notice_integration_enabled ||
3387                            options.gdpr.consent_magic_integration_enabled ||
3388                            options.gdpr.cookie_law_info_integration_enabled;
3389                        // Update eventID
3390
3391                        // send event from server if they were block by gdpr or need send with delay
3392                        if( options.ajaxForServerEvent || isApiDisabled || event.delay > 0 || event.type !== "static" ){
3393
3394                            var json = {
3395                                action: 'pys_tiktok_api_event',
3396                                pixel: TikTok.tag(),
3397                                event: name,
3398                                event_slug: event.e_id,
3399                                ids: ids,
3400                                data:params,
3401                                url:window.location.href,
3402                                event_id:params.eventID,
3403                                ajax_event:options.ajax_event
3404                            };
3405
3406                            let delay = 0;
3407                            try {
3408                                if (sessionStorage) {
3409                                    Object.keys(sessionStorage)
3410                                        .filter(key => key.startsWith('wc_fragments_'))
3411                                        .forEach((key) => {
3412                                            let value = sessionStorage.getItem(key);
3413                                            if (event.e_id === 'woo_add_to_cart_on_button_click') {
3414                                                delay = 2000;
3415                                            }
3416                                        });
3417                                }
3418                            } catch (error) {
3419                                console.error('sessionStorage is not accessible:', error);
3420                            }
3421
3422
3423                            if(event.hasOwnProperty('woo_order')) {
3424                                json['woo_order'] = event.woo_order;
3425                            }
3426
3427                            if(event.hasOwnProperty('edd_order')) {
3428                                json['edd_order'] = event.edd_order;
3429                            }
3430                            if (event.e_id === "automatic_event_internal_link" || event.e_id === "automatic_event_outbound_link" || name == 'PageView') {
3431                                delay = delay === 0 ? 500 : delay;
3432                                setTimeout(() => Utils.sendServerAjaxRequest(options.ajaxUrl, json), delay);
3433                            } else if (event.type != 'static') {
3434                                setTimeout(() => Utils.sendServerAjaxRequest(options.ajaxUrl, json), delay);
3435                            }
3436
3437                            if ( ( event.type == 'static' && options.ajaxForServerStaticEvent ) || ( event.hasOwnProperty( 'ajaxFire' ) && event.ajaxFire ) ) {
3438                                setTimeout( () => Utils.sendServerAjaxRequest( options.ajaxUrl, json ), delay );
3439                            }
3440                        }
3441                    }
3442                }
3443            },
3444
3445            onClickEvent: function (event) {
3446                this.fireEvent(event.name, event);
3447            },
3448
3449            onWooAddToCartOnSingleEvent: function (product_id, qty, product_type, is_external, $form) {
3450
3451                window.pysWooProductData = window.pysWooProductData || [];
3452                if (!options.dynamicEvents.woo_add_to_cart_on_button_click.hasOwnProperty(this.tag()))
3453                    return;
3454
3455                if (window.pysWooProductData.hasOwnProperty(product_id)) {
3456                    if (window.pysWooProductData[product_id].hasOwnProperty(this.tag())) {
3457
3458                        var event = Utils.clone(options.dynamicEvents.woo_add_to_cart_on_button_click[this.tag()]);
3459
3460                        Utils.copyProperties(window.pysWooProductData[product_id][this.tag()]['params'], event.params);
3461
3462                        // maybe customize value option
3463                        if (options.woo.addToCartOnButtonValueEnabled && options.woo.addToCartOnButtonValueOption !== 'global') {
3464
3465                            if (product_type === Utils.PRODUCT_BUNDLE) {
3466                                var data = $(".bundle_form .bundle_data").data("bundle_form_data");
3467                                var items_sum = getBundlePriceOnSingleProduct(data);
3468                                event.params.value = (parseFloat(data.base_price) + items_sum) * qty;
3469                            } else {
3470                                event.params.value = event.params.value * qty;
3471                            }
3472                        }
3473
3474                        event.params.quantity = qty;
3475
3476                        this.fireEvent(event.name, event);
3477
3478                    }
3479                }
3480            },
3481
3482            onWooAddToCartOnButtonEvent: function (product_id) {
3483                if(!options.dynamicEvents.woo_add_to_cart_on_button_click.hasOwnProperty(this.tag()))
3484                    return;
3485
3486                if (window.pysWooProductData.hasOwnProperty(product_id)) {
3487                    if (window.pysWooProductData[product_id].hasOwnProperty(this.tag())) {
3488                        var productData = window.pysWooProductData[product_id][this.tag()]
3489                        var event = Utils.clone(options.dynamicEvents.woo_add_to_cart_on_button_click[this.tag()])
3490
3491                        Utils.copyProperties(productData['params'], event.params)
3492                        event.pixelIds = productData['pixelIds'];
3493                        this.fireEvent(event.name, event);
3494                    }
3495                }
3496            },
3497
3498            onEddAddToCartOnButtonEvent : function (download_id, price_index, qty) {
3499                if(!options.dynamicEvents.edd_add_to_cart_on_button_click.hasOwnProperty(this.tag()))
3500                    return;
3501                var event = Utils.clone(options.dynamicEvents.edd_add_to_cart_on_button_click[this.tag()]);
3502
3503
3504                if (window.pysEddProductData.hasOwnProperty(download_id)) {
3505
3506                    var index;
3507
3508                    if (price_index) {
3509                        index = download_id + '_' + price_index;
3510                    } else {
3511                        index = download_id;
3512                    }
3513
3514                    if (window.pysEddProductData[download_id].hasOwnProperty(index)) {
3515                        if (window.pysEddProductData[download_id][index].hasOwnProperty(this.tag())) {
3516
3517                            Utils.copyProperties(window.pysEddProductData[download_id][index][this.tag()].params, event.params);
3518                            this.fireEvent(event.name,event);
3519
3520                        }
3521                    }
3522
3523                }
3524            },
3525
3526            onPageScroll: function (event) {
3527                if (initialized && this.isEnabled()) {
3528                    this.fireEvent(event.name, event);
3529                }
3530            },
3531
3532            onWatchVideo: function (event) {
3533                if (initialized && this.isEnabled() && !event.fired) {
3534                    this.fireEvent(event.name, event);
3535                }
3536            },
3537
3538            onCommentEvent: function (event) {
3539                if (initialized && this.isEnabled()) {
3540                    this.fireEvent(event.name, event);
3541                }
3542            },
3543
3544            onAdSenseEvent: function (event) {
3545                if (initialized && this.isEnabled()) {
3546                    this.fireEvent(event.name, event);
3547                }
3548            },
3549
3550            onTime: function (event) {
3551                if (initialized && this.isEnabled()) {
3552                    this.fireEvent(event.name, event);
3553                }
3554            },
3555        }
3556    }(options);
3557
3558    var Facebook = function (options) {
3559
3560        var defaultEventTypes = [
3561            'PageView',
3562            'ViewContent',
3563            'Search',
3564            'AddToCart',
3565            'AddToWishlist',
3566            'InitiateCheckout',
3567            'AddPaymentInfo',
3568            'Purchase',
3569            'Lead',
3570
3571            'Subscribe',
3572            'CustomizeProduct',
3573            'FindLocation',
3574            'StartTrial',
3575            'SubmitApplication',
3576            'Schedule',
3577            'Contact',
3578            'Donate'
3579        ];
3580
3581        var notCachedEventsIds = new Array();
3582        var isAddToCartFromJs =  options.woo.hasOwnProperty("addToCartCatchMethod")
3583            && options.woo.addToCartCatchMethod === "add_cart_js";
3584        if(!isAddToCartFromJs) {
3585            notCachedEventsIds.push('woo_add_to_cart_on_button_click')
3586        }
3587
3588        var initialized = false;
3589
3590        var genereateFbp = function (){
3591            return !Cookies.get('_fbp') ? 'fb.1.'+Date.now()+'.'+Math.floor(1000000000 + Math.random() * 9000000000) : Cookies.get('_fbp');
3592        };
3593        var genereateFbc = function (){
3594            return getUrlParameter('fbclid') ? 'fb.1.'+Date.now()+'.'+getUrlParameter('fbclid') : ''
3595        };
3596
3597        var configuredPixels = new Array();
3598        function fireEvent(name, event) {
3599
3600
3601            if(typeof window.pys_event_data_filter === "function" && window.pys_disable_event_filter(name,'facebook')) {
3602                return;
3603            }
3604
3605            var data = event.params;
3606            var ids = event.pixelIds.filter(function (pixelId) {
3607                return !Utils.hideMatchingPixel(pixelId, 'facebook');
3608            });
3609
3610            var actionType = defaultEventTypes.includes(name) ? 'trackSingle' : 'trackSingleCustom';
3611
3612            var params = {};
3613
3614            Utils.copyProperties(data, params);
3615            Utils.copyProperties(Utils.getRequestParams(), params);
3616            Utils.copyProperties(Utils.getRequestParams(), data);
3617
3618            params = Facebook.filterParams(params);
3619
3620
3621            if(options.facebook.serverApiEnabled) {
3622                if(event.e_id === "woo_remove_from_cart" ) {
3623                    Facebook.updateEventId(event.name);
3624                    event.eventID = Facebook.getEventId(event.name);
3625                } else if(!notCachedEventsIds.includes(event.e_id)) {
3626                    var isApiDisabled = options.gdpr.all_disabled_by_api ||
3627                        options.gdpr.facebook_disabled_by_api ||
3628                        options.gdpr.cookiebot_integration_enabled ||
3629                        options.gdpr.cookie_notice_integration_enabled ||
3630                        options.gdpr.consent_magic_integration_enabled ||
3631                        options.gdpr.cookie_law_info_integration_enabled;
3632                    // Update eventID
3633
3634                    event.eventID = Utils.generateUniqueId(event);
3635
3636                    if(Cookies.get('_fbp')){
3637                        params._fbp = Cookies.get('_fbp');
3638                    }
3639                    if(Cookies.get('_fbc')){
3640                        params._fbc = Cookies.get('_fbc');
3641                    }
3642                    // send event from server if they was bloc by gdpr or need send with delay
3643                    if( options.ajaxForServerEvent || isApiDisabled ){
3644                        var json = {
3645                            action: 'pys_api_event',
3646                            pixel: 'facebook',
3647                            event: name,
3648                            event_slug: event.e_id,
3649                            ids: ids,
3650                            data:params,
3651                            url:window.location.href,
3652                            eventID:event.eventID,
3653                            ajax_event:options.ajax_event
3654                        };
3655
3656                        if(event.hasOwnProperty('woo_order')) {
3657                            json['woo_order'] = event.woo_order;
3658                        }
3659
3660                        if(event.hasOwnProperty('edd_order')) {
3661                            json['edd_order'] = event.edd_order;
3662                        }
3663
3664                        let delay = 0;
3665                        try {
3666                            if (sessionStorage) {
3667                                Object.keys(sessionStorage)
3668                                    .filter(key => key.startsWith('wc_fragments_'))
3669                                    .forEach((key) => {
3670                                        let value = sessionStorage.getItem(key);
3671                                        if (event.e_id === 'woo_add_to_cart_on_button_click') {
3672                                            delay = 2000;
3673                                        }
3674                                    });
3675                            }
3676                        } catch (error) {
3677                            console.error('sessionStorage is not accessible:', error);
3678                        }
3679
3680                        if (event.e_id === "automatic_event_internal_link" || event.e_id === "automatic_event_outbound_link") {
3681                            delay = delay === 0 ? 500 : delay;
3682                            setTimeout(() => Utils.sendServerAjaxRequest(options.ajaxUrl, json), delay);
3683                        } else if (event.type != 'static') {
3684                            setTimeout(() => Utils.sendServerAjaxRequest(options.ajaxUrl, json), delay);
3685                        }
3686
3687                        if ( ( event.type == 'static' && options.ajaxForServerStaticEvent ) || ( event.hasOwnProperty( 'ajaxFire' ) && event.ajaxFire ) ) {
3688                            setTimeout( () => Utils.sendServerAjaxRequest( options.ajaxUrl, json ), delay );
3689                        }
3690                    }
3691
3692                    if( event.e_id !== "automatic_event_signup" && name == "CompleteRegistration" && options.facebook.wooCRSendFromServer ) {
3693                        return;
3694                    }
3695                }
3696
3697            }
3698            delete params._fbp;
3699            delete params._fbc;
3700            if (options.debug) {
3701                console.log('[Facebook] ' + name, params,"pixel_ids",ids,"eventID",event.eventID);
3702            }
3703            // fire event for each pixel id
3704            ids.forEach(function (pixelId) {
3705                // add eventID for deduplicate events @see https://developers.facebook.com/docs/marketing-api/conversions-api/deduplicate-pixel-and-server-events/
3706                var args = {};
3707                if(options.facebook.serverApiEnabled && event.hasOwnProperty('eventID')) {
3708                    args.eventID = event.eventID;
3709                }
3710                Facebook.maybeInitPixel(pixelId);
3711                fbq(actionType,pixelId, name, params,args);
3712            });
3713            var customEvent = new CustomEvent('facebook_event_sent', {
3714                detail: {
3715                    eventName: name,
3716                    params: params,
3717                    pixel_ids: ids
3718                }
3719            });
3720            window.dispatchEvent(customEvent);
3721        }
3722
3723        /**
3724         * Public API
3725         */
3726        return {
3727            tag: function() {
3728                return "facebook";
3729            },
3730            isEnabled: function () {
3731                return options.hasOwnProperty('facebook');
3732            },
3733            getHidePixel: function(){
3734                if(this.isEnabled() && options.facebook.hasOwnProperty('hide_pixels'))
3735                {
3736                    return options.facebook.hide_pixels;
3737                }
3738                return [];
3739            },
3740            initEventIdCookies: function (key) {
3741                var ids = {};
3742                ids[key] = pys_generate_token(36)
3743                Cookies.set('pys_fb_event_id', JSON.stringify(ids), {path: '/',domain: domain});
3744            },
3745
3746            updateEventId:function(key) {
3747                var cooData = Cookies.get("pys_fb_event_id")
3748                if(cooData === undefined) {
3749                    this.initEventIdCookies(key);
3750                } else {
3751                    var data = JSON.parse(cooData);
3752                    data[key] = pys_generate_token(36);
3753                    Cookies.set('pys_fb_event_id', JSON.stringify(data), {path: '/',domain: domain} );
3754                }
3755            },
3756
3757            getEventId:function (key) {
3758                var data = Cookies.get("pys_fb_event_id");
3759                if(data === undefined) {
3760                    this.initEventIdCookies(key);
3761                    data = Cookies.get("pys_fb_event_id");
3762                }
3763                return JSON.parse(data)[key];
3764            },
3765
3766            disable: function () {
3767                initialized = false;
3768            },
3769
3770            filterParams: function (params) {
3771                var filteredParams = {};
3772
3773                if (options.facebook.hasOwnProperty('enabled_medical') && options.facebook.enabled_medical && options.facebook.hasOwnProperty('do_not_track_medical_param')) {
3774                    // Remove empty strings from the array
3775                    options.facebook.do_not_track_medical_param = options.facebook.do_not_track_medical_param.filter(Boolean);
3776                    for (const key in params) {
3777                        if (Array.isArray(options.facebook.do_not_track_medical_param)) {
3778                            if (!options.facebook.do_not_track_medical_param.includes(key)) {
3779                                filteredParams[key] = params[key];
3780                            }
3781                        }
3782                    }
3783                }
3784                else {
3785                    Utils.copyProperties(params, filteredParams);
3786                }
3787                return filteredParams;
3788            },
3789
3790            /**
3791             * Load pixel's JS
3792             */
3793            loadPixel: function () {
3794                if (initialized || !this.isEnabled() || !Utils.consentGiven('facebook')) {
3795                    return;
3796                }
3797
3798                ! function (f, b, e, v, n, t, s) {
3799                    if (f.fbq) return;
3800                    n = f.fbq = function () {
3801                        n.callMethod ?
3802                            n.callMethod.apply(n, arguments) : n.queue.push(arguments)
3803                    };
3804                    if (!f._fbq) f._fbq = n;
3805                    n.push = n;
3806                    n.loaded = !0;
3807                    n.version = '2.0';
3808                    n.agent = 'dvpixelyoursite';
3809                    n.queue = [];
3810                    t = b.createElement(e);
3811                    t.async = !0;
3812                    t.src = v;
3813                    s = b.getElementsByTagName(e)[0];
3814                    s.parentNode.insertBefore(t, s)
3815                }(window,
3816                    document, 'script', 'https://connect.facebook.net/en_US/fbevents.js');
3817                let expires = parseInt(options.cookie_duration);
3818                if(!Cookies.get('_fbp')) {
3819                    Cookies.set('_fbp',genereateFbp(),  { expires: expires,path: '/',domain: domain });
3820                }
3821
3822                if(getUrlParameter('fbclid')) {
3823                    Cookies.set('_fbc',genereateFbc(),  { expires: expires,path: '/',domain: domain });
3824                }
3825                var ids = options.facebook.pixelIds.filter(function (pixelId) {
3826                    return !Utils.hideMatchingPixel(pixelId, 'facebook');
3827                });
3828                // initialize default pixel
3829                ids.forEach(function (pixelId) {
3830                    Facebook.maybeInitPixel(pixelId);
3831                });
3832                initialized = true;
3833
3834                Utils.fireStaticEvents('facebook');
3835
3836            },
3837            advancedMatching: function () {
3838                if(options.facebook.advancedMatchingEnabled) {
3839                    let advancedMatchingForm = Utils.getAdvancedFormData();
3840                    let advancedMatching = {};
3841                    if(Object.keys(options.facebook.advancedMatching).length > 0) {
3842                        advancedMatching = options.facebook.advancedMatching;
3843                    }
3844
3845                    if(!advancedMatching.hasOwnProperty("em")
3846                        && advancedMatchingForm.hasOwnProperty("email") && advancedMatchingForm["email"].length > 0) {
3847                        advancedMatching["em"] = advancedMatchingForm["email"];
3848                    }
3849                    if(!advancedMatching.hasOwnProperty("ph")
3850                        && advancedMatchingForm.hasOwnProperty("phone") && advancedMatchingForm["phone"].length > 0) {
3851                        advancedMatching["ph"] = advancedMatchingForm["phone"];
3852                    }
3853                    if(!advancedMatching.hasOwnProperty("fn")
3854                        && advancedMatchingForm.hasOwnProperty("first_name") && advancedMatchingForm["first_name"].length > 0) {
3855                        advancedMatching["fn"] = advancedMatchingForm["first_name"];
3856                    }
3857                    if(!advancedMatching.hasOwnProperty("ln")
3858                        && advancedMatchingForm.hasOwnProperty("last_name") && advancedMatchingForm["last_name"].length > 0) {
3859                        advancedMatching["ln"] = advancedMatchingForm["last_name"];
3860                    }
3861                    if(!advancedMatching.hasOwnProperty("external_id")){
3862                        if (Cookies.get('pbid')) {
3863                            advancedMatching["external_id"] = Cookies.get('pbid');
3864                        }
3865                    }
3866                    else if(advancedMatching.hasOwnProperty("external_id") && advancedMatching.external_id != Cookies.get('pbid'))
3867                    {
3868                        advancedMatching["external_id"] = Cookies.get('pbid') ? Cookies.get('pbid') : advancedMatching.external_id;
3869                    }
3870
3871                    if(Object.keys(advancedMatching).length > 0) {
3872                        return advancedMatching;
3873                    }
3874                }
3875                return false
3876            },
3877            maybeInitPixel: function(pixelId) {
3878
3879                if(configuredPixels.includes(pixelId)) return;
3880
3881                if (options.facebook.removeMetadata || Utils.hideMatchingPixel(pixelId, this.tag())) {
3882                    fbq('set', 'autoConfig', false, pixelId);
3883                }
3884                let advancedMatching = Facebook.advancedMatching();
3885
3886                if ( +options.facebook.meta_ldu === 1  ) {
3887                    fbq( 'dataProcessingOptions', [ 'LDU' ], 0, 0 );
3888                }
3889
3890                if (options.gdpr.consent_magic_integration_enabled && typeof CS_Data !== "undefined") {
3891                    if(!advancedMatching) {
3892                        fbq('init', pixelId);
3893                    } else {
3894                        var test_prefix = CS_Data.test_prefix;
3895                        var cs_advanced_matching = Cookies.get('cs_enabled_advanced_matching'+test_prefix);
3896                        if (jQuery('#cs_enabled_advanced_matching'+test_prefix).length > 0) {
3897                            if (cs_advanced_matching == 'yes') {
3898                                fbq('init', pixelId, advancedMatching);
3899                            } else {
3900                                fbq('init', pixelId);
3901                            }
3902                        } else {
3903                            fbq('init', pixelId, advancedMatching);
3904                        }
3905                    }
3906                } else {
3907                    if(!advancedMatching) {
3908                        fbq('init', pixelId);
3909                    }  else {
3910                        fbq('init', pixelId, advancedMatching);
3911                    }
3912                }
3913                configuredPixels.push(pixelId);
3914            },
3915
3916            fireEvent: function (name, data) {
3917
3918                if (!initialized || !this.isEnabled()) {
3919                    return false;
3920                }
3921
3922                data.delay = data.delay || 0;
3923                data.params = data.params || {};
3924
3925                if (data.delay === 0) {
3926
3927                    fireEvent(name, data);
3928
3929                } else {
3930
3931                    setTimeout(function (name, params) {
3932                        fireEvent(name, params);
3933                    }, data.delay * 1000, name, data);
3934
3935                }
3936
3937                return true;
3938
3939            },
3940
3941            onAdSenseEvent: function (event) {
3942                this.fireEvent(event.name, event);
3943            },
3944
3945            onClickEvent: function (event) {
3946                this.fireEvent(event.name, event);
3947            },
3948
3949            onWatchVideo: function (event) {
3950                this.fireEvent(event.name, event);
3951            },
3952
3953            onCommentEvent: function (event) {
3954                this.fireEvent(event.name, event);
3955            },
3956
3957            onFormEvent: function (event) {
3958                this.fireEvent(event.name, event);
3959            },
3960
3961            onDownloadEvent: function (event) {
3962                this.fireEvent(event.name, event);
3963
3964            },
3965
3966
3967            onWooAddToCartOnButtonEvent: function (product_id) {
3968
3969                window.pysWooProductData = window.pysWooProductData || [];
3970                if(!options.dynamicEvents.woo_add_to_cart_on_button_click.hasOwnProperty(this.tag()))
3971                    return;
3972
3973                if (window.pysWooProductData.hasOwnProperty(product_id)) {
3974                    if (window.pysWooProductData[product_id].hasOwnProperty('facebook')) {
3975
3976                        var event = Utils.clone(options.dynamicEvents.woo_add_to_cart_on_button_click[this.tag()])
3977
3978                        Utils.copyProperties(window.pysWooProductData[product_id]['facebook']['params'], event.params)
3979                        event.pixelIds = window.pysWooProductData[product_id]['facebook']['pixelIds'];
3980                        this.fireEvent(event.name, event);
3981                    }
3982                }
3983            },
3984
3985            onWooAddToCartOnSingleEvent: function (product_id, qty, product_type, is_external, $form) {
3986
3987                window.pysWooProductData = window.pysWooProductData || [];
3988                if(!options.dynamicEvents.woo_add_to_cart_on_button_click.hasOwnProperty(this.tag()))
3989                    return;
3990
3991                if (product_type === Utils.PRODUCT_VARIABLE && !options.facebook.wooVariableAsSimple) {
3992                    product_id = parseInt($form.find('input[name="variation_id"]').val());
3993                }
3994
3995                if (window.pysWooProductData.hasOwnProperty(product_id)) {
3996                    if (window.pysWooProductData[product_id].hasOwnProperty('facebook')) {
3997
3998                        var event = Utils.clone(options.dynamicEvents.woo_add_to_cart_on_button_click.facebook);
3999
4000
4001                        Utils.copyProperties(window.pysWooProductData[product_id]['facebook']['params'], event.params);
4002
4003                        var groupValue = 0;
4004                        if(product_type === Utils.PRODUCT_GROUPED ) {
4005                            $form.find(".woocommerce-grouped-product-list .qty").each(function(index){
4006                                var childId = $(this).attr('name').replaceAll("quantity[","").replaceAll("]","");
4007                                var quantity = parseInt($(this).val());
4008                                if(isNaN(quantity)) {
4009                                    quantity = 0;
4010                                }
4011                                var childItem = window.pysWooProductData[product_id]['facebook'].grouped[childId];
4012
4013                                if(quantity == 0) {
4014                                    event.params.content_ids.forEach(function(el,index,array) {
4015                                        if(el == childItem.content_id) {
4016                                            array.splice(index, 1);
4017                                        }
4018                                    });
4019                                }
4020
4021                                if(event.params.hasOwnProperty('contents')) {
4022                                    event.params.contents.forEac
4022h(function(el,index,array) {
4023                                        if(el.id == childItem.content_id) {
4024                                            if(quantity > 0){
4025                                                el.quantity = quantity;
4026                                            } else {
4027                                                array.splice(index, 1);
4028                                            }
4029                                        }
4030                                    });
4031                                }
4032
4033
4034                                groupValue += childItem.price * quantity;
4035                            });
4036                            if(groupValue == 0) return; // skip if no items selected
4037                        }
4038
4039
4040
4041                        // maybe customize value option
4042                        if (options.woo.addToCartOnButtonValueEnabled && options.woo.addToCartOnButtonValueOption !== 'global') {
4043
4044                            if(product_type === Utils.PRODUCT_GROUPED) {
4045                                event.params.value = groupValue;
4046                            } else if(product_type === Utils.PRODUCT_BUNDLE) {
4047                                var data = $(".bundle_form .bundle_data").data("bundle_form_data");
4048                                var items_sum = getBundlePriceOnSingleProduct(data);
4049                                event.params.value = (parseFloat(data.base_price) + items_sum )* qty;
4050                            } else {
4051                                event.params.value = event.params.value * qty;
4052                            }
4053                        }
4054
4055                        // only when non Facebook for WooCommerce logic used
4056                        if (event.params.hasOwnProperty('contents') && product_type !== Utils.PRODUCT_GROUPED) {
4057                            event.params.contents[0].quantity = qty;
4058
4059                        }
4060
4061                        var event_name = is_external ? options.woo.affiliateEventName : event.name;
4062
4063                        this.fireEvent(event_name, event);
4064
4065                    }
4066                }
4067
4068            },
4069
4070            onWooRemoveFromCartEvent: function (event) {
4071                this.fireEvent(event.name, event);
4072            },
4073
4074            onWooAffiliateEvent: function (product_id) {
4075                if(!options.dynamicEvents.woo_affiliate.hasOwnProperty(this.tag()))
4076                    return;
4077                var event = Utils.clone(options.dynamicEvents.woo_affiliate[this.tag()]);
4078
4079
4080                if (window.pysWooProductData.hasOwnProperty(product_id)) {
4081                    if (window.pysWooProductData[product_id].hasOwnProperty('facebook')) {
4082
4083                        Utils.copyProperties(window.pysWooProductData[product_id][this.tag()].params, event.params)
4084                        this.fireEvent(options.woo.affiliateEventName, event);
4085
4086                    }
4087                }
4088
4089            },
4090
4091            onWooPayPalEvent: function (event) {
4092                this.fireEvent(event.name, event);
4093            },
4094
4095            onEddAddToCartOnButtonEvent: function (download_id, price_index, qty) {
4096                if(!options.dynamicEvents.edd_add_to_cart_on_button_click.hasOwnProperty(this.tag()))
4097                    return;
4098                var event = Utils.clone(options.dynamicEvents.edd_add_to_cart_on_button_click[this.tag()]);
4099
4100                if (window.pysEddProductData.hasOwnProperty(download_id)) {
4101
4102                    var index;
4103
4104                    if (price_index) {
4105                        index = download_id + '_' + price_index;
4106                    } else {
4107                        index = download_id;
4108                    }
4109
4110                    if (window.pysEddProductData[download_id].hasOwnProperty(index)) {
4111                        if (window.pysEddProductData[download_id][index].hasOwnProperty('facebook')) {
4112
4113                            Utils.copyProperties(window.pysEddProductData[download_id][index]['facebook']["params"], event.params)
4114
4115                            // maybe customize value option
4116                            if (options.edd.addToCartOnButtonValueEnabled && options.edd.addToCartOnButtonValueOption !== 'global') {
4117                                event.params.value = event.params.value * qty;
4118                            }
4119
4120                            // update contents qty param
4121                            var contents = event.params.contents;
4122                            contents[0].quantity = qty;
4123                            event.params.contents = contents;
4124
4125                            this.fireEvent(event.name,event);
4126
4127                        }
4128                    }
4129
4130                }
4131
4132            },
4133
4134            onEddRemoveFromCartEvent: function (event) {
4135                this.fireEvent(event.name, event);
4136            },
4137            onPageScroll: function (event) {
4138                this.fireEvent(event.name, event);
4139            },
4140            onTime: function (event) {
4141                this.fireEvent(event.name, event);
4142            },
4143        };
4144
4145    }(options);
4146
4147    var Analytics = function (options) {
4148
4149        var initialized = false;
4150        var isAllowEnhancedConversions = false;
4151        /**
4152         * Fires event
4153         *
4154         * @link: https://developers.google.com/analytics/devguides/collection/gtagjs/sending-data
4155         * @link: https://developers.google.com/analytics/devguides/collection/gtagjs/events
4156         * @link: https://developers.google.com/gtagjs/reference/event
4157         * @link: https://developers.google.com/gtagjs/reference/parameter
4158         *
4159         * @link: https://developers.google.com/analytics/devguides/collection/gtagjs/custom-dim
4159s-mets
4160         *
4161         * @param name
4162         * @param data
4163         */
4164        function fireEvent(name, event) {
4165            if(typeof window.pys_event_data_filter === "function" && window.pys_disable_event_filter(name,'ga')) {
4166                return;
4167            }
4168
4169            var eventParams = event.params;
4170            var valuesArray = Object.values(event.trackingIds);
4171            var ids = valuesArray.filter(function (pixelId) {
4172                return loadTags.some(loadTag => pixelId.startsWith(loadTag)) && !Utils.hideMatchingPixel(pixelId, 'ga') && !Utils.hideMatchingPixel(pixelId, 'google_ads');
4173            })
4174
4175            Utils.copyProperties(Utils.getRequestParams(), eventParams);
4176            var _fireEvent = function (tracking_ids,name,params) {
4177
4178                params['send_to'] = tracking_ids;
4179                
4180                if (options.debug) {
4181                    console.log('[Google Analytics #' + tracking_ids + '] ' + name, params);
4182                }
4183
4184                gtag('event', name, params);
4185
4186                var customEvent = new CustomEvent('gtag_event_sent', {
4187                    detail: {
4188                        eventName: name,
4189                        params: params,
4190                        pixel_ids: tracking_ids
4191                    }
4192                });
4193                window.dispatchEvent(customEvent);
4194
4195            };
4196
4197            var copyParams = Utils.copyProperties(eventParams, {}); // copy params because mapParamsTov4 can modify it
4198
4199            var params = mapParamsTov4(ids,name,copyParams)
4200
4201            params.event_id = Utils.generateUniqueId(event);
4202
4203
4204            delete params.analytics_storage;
4205            delete params.ad_storage;
4206            delete params.ad_user_data;
4207            delete params.ad_personalization;
4208
4209            if(options.hasOwnProperty('google_ads')){
4210                var conversion_event_name = event.e_id;
4211                switch ( conversion_event_name ) {
4212                    case "woo_add_to_cart_on_cart_page":
4213                    case "woo_add_to_cart_on_checkout_page":
4214                    case "woo_add_to_cart_on_button_click":
4215                        conversion_event_name = 'woo_add_to_cart';
4216                        break;
4217                    case "edd_add_to_cart_on_cart_page":
4218                    case "edd_add_to_cart_on_checkout_page":
4219                    case "edd_add_to_cart_on_button_click":
4220                        conversion_event_name = 'edd_add_to_cart';
4221                        break;
4222                    case "automatic_event_adsense":
4223                    case "automatic_event_comment":
4224                    case "automatic_event_download":
4225                    case "automatic_event_email_link":
4226                    case "automatic_event_form":
4227                    case "automatic_event_internal_link":
4228                    case "automatic_event_outbound_link":
4229                    case "automatic_event_scroll":
4230                    case "automatic_event_tel_link":
4231                    case "automatic_event_time_on_page":
4232                    case "automatic_event_video":
4233                        conversion_event_name = 'automatic_event';
4234                        break;
4235                }
4236
4237                if ( conversion_event_name !== 'automatic_event' &&
4238                    typeof options.google_ads[conversion_event_name + '_conversion_track'] !== 'undefined' ) {
4239                    const conversionTrack = options.google_ads[ conversion_event_name + '_conversion_track' ];
4240
4241                    if ( conversionTrack === 'conversion' ) {
4242                        ids = ids.map(id => id.split('/')[0])
4243                    }
4244                }
4245            }
4246
4247
4248            _fireEvent(ids, name, params);
4249            if(event.hasOwnProperty('unify') && event.unify){
4250                isTrackEventForGA.push(name);
4251            }
4252        }
4253
4254        function normalizeEventName(eventName) {
4255
4256            var matches = {
4257                ViewContent: 'view_item',
4258                AddToCart: 'add_to_cart',
4259                AddToWishList: 'add_to_wishlist',
4260                InitiateCheckout: 'begin_checkout',
4261                Purchase: 'purchase',
4262                Lead: 'generate_lead',
4263                CompleteRegistration: 'sign_up',
4264                AddPaymentInfo: 'set_checkout_option'
4265            };
4266
4267            return matches.hasOwnProperty(eventName) ? matches[eventName] : eventName;
4268
4269        }
4270
4271        function mapParamsTov4(tag,name,param) {
4272            //GA4 automatically collects a number of parameters for all events
4273            var hasGA4Tag = false;
4274
4275            // end
4276            if (Array.isArray(tag)) {
4277                hasGA4Tag = tag.some(function (element) {
4278                    return isv4(element);
4279                });
4280            } else if(isv4(tag)) {
4281                // tag является строкой и соответствует GA4
4282                hasGA4Tag = true;
4283            }
4284            if(hasGA4Tag) {
4285                delete param.event_category;
4286                delete param.event_label;
4287                delete param.ecomm_prodid;
4288                delete param.ecomm_pagetype;
4289                delete param.ecomm_totalvalue;
4290                if(name === 'search') {
4291                    param['search'] = param.search_term;
4292                    delete param.search_term;
4293                    delete param.dynx_itemid;
4294                    delete param.dynx_pagetype;
4295                    delete param.dynx_totalvalue;
4296                }
4297            }
4298            return param;
4299        }
4300
4301        function isv4(tag) {
4302            return tag.indexOf('G') === 0;
4303        }
4304
4305        /**
4306         * Public API
4307         */
4308        return {
4309            tag: function() {
4310                return "ga";
4311            },
4312            isEnabled: function () {
4313                return options.hasOwnProperty('ga');
4314            },
4315            getHidePixel: function(){
4316                if(this.isEnabled() && options.ga.hasOwnProperty('hide_pixels'))
4317                {
4318                    return options.ga.hide_pixels;
4319                }
4320                return [];
4321            },
4322            disable: function () {
4323                initialized = false;
4324            },
4325            updateEnhancedConversionData : function () {
4326                if (!initialized || !this.isEnabled()) {
4327                    return;
4328                }
4329                if(options.hasOwnProperty("tracking_analytics") && options.tracking_analytics.hasOwnProperty("userDataEnable") && options.tracking_analytics.userDataEnable) {
4330                    var advanced = Utils.getAdvancedMergeFormData();
4331                    if (Object.keys(advanced).length > 0) {
4332                        gtag('set', 'user_data', advanced);
4333                    }
4334                }
4335            },
4336            loadPixel: function () {
4337                if (initialized || !this.isEnabled() || !Utils.consentGiven('analytics')) {
4338                    return;
4339                }
4340
4341
4342                for (var i = 0; i < options.ga.trackingIds.length; i++) {
4343                    var trackingId = options.ga.trackingIds[i];
4344                    if (!Utils.hideMatchingPixel(trackingId, 'ga')) {
4345                        Utils.loadGoogleTag(trackingId);
4346                        break;
4347                    }
4348                }
4349
4350                var cd = {
4351                    'dimension1': 'event_hour',
4352                    'dimension2': 'event_day',
4353                    'dimension3': 'event_month'
4354                };
4355
4356                // configure Dynamic Remarketing CDs
4357                if (options.ga.retargetingLogic === 'ecomm') {
4358                    cd.dimension4 = 'ecomm_prodid';
4359                    cd.dimension5 = 'ecomm_pagetype';
4360                    cd.dimension6 = 'ecomm_totalvalue';
4361                } else {
4362                    cd.dimension4 = 'dynx_itemid';
4363                    cd.dimension5 = 'dynx_pagetype';
4364                    cd.dimension6 = 'dynx_totalvalue';
4365                }
4366
4367                if(options.hasOwnProperty("tracking_analytics") && options.tracking_analytics.hasOwnProperty("userDataEnable") && options.tracking_analytics.userDataEnable){
4368                    var advanced = Utils.getAdvancedMergeFormData();
4369                    if(Object.keys(advanced).length > 0){
4370                        gtag('set', 'user_data', advanced);
4371                    }
4372                }
4373
4374                var config = {
4375                    'custom_map': cd
4376                };
4377
4378                if(options.user_id && options.user_id != 0) {
4379                    config.user_id = options.user_id;
4380                }
4381                config.url_passthrough = options.ga.url_passthrough;
4382                // Cross-Domain tracking
4383                if (options.ga.crossDomainEnabled) {
4384                    config.linker = {
4385                        accept_incoming: options.ga.crossDomainAcceptIncoming,
4386                        domains: options.ga.crossDomainDomains
4387                    };
4388                }
4389
4390                var ids = options.ga.trackingIds.filter(function (pixelId) {
4391                    return !Utils.hideMatchingPixel(pixelId, 'ga');
4392                });
4393                loadTags.push(...ids);
4394                ids.forEach(function (trackingId,index) {
4395
4396                    var obj = options.ga.isDebugEnabled;
4397                    var searchValue = "index_"+index;
4398                    var config_for_tag = Object.assign({}, config);
4399                    config_for_tag.debug_mode = false;
4400                    config_for_tag.send_page_view = !options.ga.custom_page_view_event;
4401                    for (var key in obj) {
4402                        if (obj[key] === searchValue) {
4403                            config_for_tag.debug_mode = true;
4404                            break;
4405                        }
4406                    }
4407                    if(!config_for_tag.debug_mode)
4408                    {
4409                        delete config_for_tag.debug_mode;
4410                    }
4411
4412                    if(isv4(trackingId)) {
4413                        if(options.ga.disableAdvertisingPersonalization) {
4414                            config_for_tag.allow_ad_personalization_signals = false
4415                        }
4416                    }
4417                    if(options.ga.hasOwnProperty('additionalConfig')){
4418                        if(options.ga.additionalConfig.hasOwnProperty(trackingId) && options.ga.additionalConfig[trackingId]){
4419                            config_for_tag.first_party_collection = options.ga.additionalConfig[trackingId].first_party_collection;
4420                        }
4421
4422                    }
4423                    if(options.ga.hasOwnProperty('serverContainerUrls')){
4424                        if(options.ga.serverContainerUrls.hasOwnProperty(trackingId) && options.ga.serverContainerUrls[trackingId].enable_server_container != false){
4425                            if(options.ga.serverContainerUrls[trackingId].server_container_url != ''){
4426                                config_for_tag.server_container_url = options.ga.serverContainerUrls[trackingId].server_container_url;
4427                            }
4428                            if(options.ga.serverContainerUrls[trackingId].transport_url != ''){
4429                                config_for_tag.transport_url = options.ga.serverContainerUrls[trackingId].transport_url;
4430                            }
4431                        }
4432                    }
4433                    if (options.gdpr.cookiebot_integration_enabled && typeof Cookiebot !== 'undefined') {
4434                        var cookiebot_consent_category = options.gdpr['cookiebot_analytics_consent_category'];
4435                        if (options.gdpr['analytics_prior_consent_enabled']) {
4436                            if (Cookiebot.consented === true && Cookiebot.consent[cookiebot_consent_category]) {
4437                                gtag('config', trackingId, config_for_tag);
4438                            }
4439                        } else {
4440                            if (Cookiebot.consent[cookiebot_consent_category]) {
4441                                gtag('config', trackingId, config_for_tag);
4442                            }
4443                        }
4444                    }
4445                    else
4446                    {
4447                        gtag('config', trackingId, config_for_tag);
4448                    }
4449                });
4450                if(!isAdsLoad && GAds.isEnabled() && options.google_ads.conversion_ids.length > 0 && Utils.consentGiven('google_ads')) {
4451                    for (var i = 0; i < options.google_ads.conversion_ids.length; i++) {
4452                        var trackingId = options.google_ads.conversion_ids[i];
4453                        if (!Utils.hideMatchingPixel(trackingId, 'google_ads')) {
4454                            Utils.loadGoogleTag(trackingId);
4455                            break;
4456                        }
4457                    }
4458                    var ids = options.google_ads.conversion_ids.filter(function (pixelId) {
4459                        return !Utils.hideMatchingPixel(pixelId, 'google_ads');
4460                    });
4461                    loadTags.push(...ids);
4462                    // configure conversion ids
4463                    ids.forEach(function (conversion_id,index) {
4464
4465                        gtag('config', conversion_id);
4466
4467                        if(options.google_ads.enhanced_conversion.includes("index_"+index)) {
4468                            isAllowEnhancedConversions = true
4469                            gtag('config', conversion_id,{ 'allow_enhanced_conversions':true });
4470                        }
4471
4472                    });
4473                    isAdsLoad = true;
4474                }
4475
4476
4477                initialized = true;
4478
4479                Utils.fireStaticEvents('ga');
4480                $( document).trigger( "analytics_initialized")
4481            },
4482
4483            fireEvent: function (name, data) {
4484
4485                if (!initialized || !this.isEnabled()) {
4486                    return false;
4487                }
4488
4489                data.delay = data.delay || 0;
4490                data.params = data.params || {};
4491
4492                if (data.delay === 0) {
4493
4494                    fireEvent(name, data);
4495
4496                } else {
4497
4498                    setTimeout(function (name, params) {
4499                        fireEvent(name, params);
4500                    }, data.delay * 1000, name, data);
4501
4502                }
4503
4504                return true;
4505
4506            },
4507
4508            onAdSenseEvent: function (event) {
4509                this.fireEvent(event.name, event);
4510            },
4511
4512            onClickEvent: function (event) {
4513                this.fireEvent(event.name, event);
4514            },
4515
4516            onWatchVideo: function (event) {
4517                if(!event.hasOwnProperty("youtube_disabled")
4518                    || !event.youtube_disabled
4519                    || event.params.video_type !== "youtube") {
4520                    this.fireEvent(event.name, event);
4521                }
4522            },
4523
4524            onCommentEvent: function (event) {
4525
4526                this.fireEvent(event.name, event);
4527
4528            },
4529
4530            onFormEvent: function (event) {
4531
4532                this.fireEvent(event.name, event);
4533
4534            },
4535
4536            onDownloadEvent: function (event) {
4537
4538                this.fireEvent(event.name, event);
4539
4540            },
4541
4542            onWooAddToCartOnButtonEvent: function (product_id, prod_info = null) {
4543                if(!options.dynamicEvents.woo_add_to_cart_on_button_click.hasOwnProperty(this.tag()))
4544                    return;
4545
4546                if (window.pysWooProductData.hasOwnProperty(product_id)) {
4547                    if (window.pysWooProductData[product_id].hasOwnProperty('ga')) {
4548                        var event = Utils.clone(options.dynamicEvents.woo_add_to_cart_on_button_click[this.tag()]);
4549                        Utils.copyProperties(window.pysWooProductData[product_id]['ga'].params, event.params)
4550                        event.trackingIds = window.pysWooProductData[product_id]['ga']['trackingIds'];
4551                        if(prod_info)
4552                        {
4553                            if(prod_info['pys_list_name_productlist_id'])
4554                            {
4555                                event.params.items[0]['item_list_id'] = prod_info['pys_list_name_productlist_id']
4556                            }
4557                            if(prod_info['pys_list_name_productlist_name'])
4558                            {
4559                                event.params.items[0]['item_list_name'] =prod_info['pys_list_name_productlist_name']
4560                            }
4561                        }
4562                        this.fireEvent(event.name, event);
4563                    }
4564                }
4565
4566            },
4567
4568            onWooAddToCartOnSingleEvent: function (product_id, qty, product_type, is_external, $form, prod_info) {
4569
4570                window.pysWooProductData = window.pysWooProductData || [];
4571
4572                if(!options.dynamicEvents.woo_add_to_cart_on_button_click.hasOwnProperty(this.tag()))
4573                    return;
4574                var event = Utils.clone(options.dynamicEvents.woo_add_to_cart_on_button_click[this.tag()]);
4575
4576                if (product_type === Utils.PRODUCT_VARIABLE && !options.ga.wooVariableAsSimple) {
4577                    product_id = parseInt($form.find('input[name="variation_id"]').val());
4578                }
4579
4580                if (window.pysWooProductData.hasOwnProperty(product_id)) {
4581                    if (window.pysWooProductData[product_id].hasOwnProperty('ga')) {
4582
4583                        Utils.copyProperties(window.pysWooProductData[product_id]['ga'].params, event.params);
4584
4585
4586                        if(product_type === Utils.PRODUCT_GROUPED ) {
4587                            var groupValue = 0;
4588                            $form.find(".woocommerce-grouped-product-list .qty").each(function(index){
4589                                var childId = $(this).attr('name').replaceAll("quantity[","").replaceAll("]","");
4590                                var quantity = parseInt($(this).val());
4591                                if(isNaN(quantity)) {
4592                                    quantity = 0;
4593                                }
4594                                var childItem = window.pysWooProductData[product_id]['ga'].grouped[childId];
4595                                event.params.items.forEach(function(el,index,array) {
4596                                    if(el.id == childItem.content_id) {
4597                                        if(quantity > 0){
4598                                            el.quantity = quantity;
4599                                            el.price = childItem.price;
4600                                        } else {
4601                                            array.splice(index, 1);
4602                                        }
4603                                    }
4604                                });
4605                                groupValue += childItem.price * quantity;
4606                            });
4607
4608                            if(options.woo.addToCartOnButtonValueEnabled &&
4609                                options.woo.addToCartOnButtonValueOption !== 'global' &&
4610                                event.params.hasOwnProperty('value')) {
4611                                event.params.value = groupValue;
4612                            }
4613
4614                            if(groupValue == 0) return; // skip if no items selected
4615                        } else {
4616                            // update items qty param
4617                            event.params.items[0].quantity = qty;
4618                        }
4619
4620                        // maybe customize value option
4621                        if (options.woo.addToCartOnButtonValueEnabled &&
4622                            options.woo.addToCartOnButtonValueOption !== 'global' &&
4623                            product_type !== Utils.PRODUCT_GROUPED)
4624                        {
4625                            if(event.params.hasOwnProperty('value')) {
4626                                event.params.value = event.params.items[0].price * qty;
4627                            }
4628                        }
4629
4630                        if(prod_info)
4631                        {
4632                            if(prod_info['pys_list_name_productlist_id'])
4633                            {
4634                                event.params.items[0]['item_list_id'] = prod_info['pys_list_name_productlist_id']
4635                            }
4636                            if(prod_info['pys_list_name_productlist_name'])
4637                            {
4638                                event.params.items[0]['item_list_name'] =prod_info['pys_list_name_productlist_name']
4639                            }
4640                        }
4641
4642                        var eventName = is_external ? options.woo.affiliateEventName : event.name;
4643                        eventName = normalizeEventName(eventName);
4644
4645                        this.fireEvent(eventName, event);
4646
4647                    }
4648                }
4649
4650            },
4651
4652            onWooCheckoutProgressStep: function (event) {
4653                this.fireEvent(event.name, event);
4654            },
4655
4656            onWooSelectContent: function (event) {
4657                const select_prod_list = {};
4658
4659                if (event.params.items[0].item_list_name !== undefined) {
4660                    select_prod_list.list_name = event.params.items[0].item_list_name;
4661                }
4662
4663                if (event.params.items[0].item_list_id !== undefined) {
4664                    select_prod_list.list_id = event.params.items[0].item_list_id;
4665                }
4666                const url = new URL(window.location.href);
4667                select_prod_list.url = url.origin + url.pathname;
4668                Cookies.set('select_prod_list', JSON.stringify(select_prod_list), { expires: 1,path: '/' });
4669                this.fireEvent(event.name, event);
4670            },
4671
4672            onWooRemoveFromCartEvent: function (event) {
4673                this.fireEvent(event.name, event);
4674            },
4675
4676            onWooAffiliateEvent: function (product_id) {
4677                if(!options.dynamicEvents.woo_affiliate.hasOwnProperty(this.tag()))
4678                    return;
4679                var event = options.dynamicEvents.woo_affiliate[this.tag()];
4680
4681                if (window.pysWooProductData.hasOwnProperty(product_id)) {
4682                    if (window.pysWooProductData[product_id].hasOwnProperty('ga')) {
4683
4684                        event = Utils.clone(event );
4685                        Utils.copyProperties(window.pysWooProductData[product_id][this.tag()], event.params)
4686                        this.fireEvent(normalizeEventName(options.woo.affiliateEventName), event);
4687
4688                    }
4689                }
4690
4691            },
4692
4693            onWooPayPalEvent: function (event) {
4694                this.fireEvent(event.name, event);
4695            },
4696
4697            onEddAddToCartOnButtonEvent: function (download_id, price_index, qty) {
4698                if(!options.dynamicEvents.edd_add_to_cart_on_button_click.hasOwnProperty(this.tag()))
4699                    return;
4700                var event = Utils.clone(options.dynamicEvents.edd_add_to_cart_on_button_click[this.tag()]);
4701
4702
4703                if (window.pysEddProductData.hasOwnProperty(download_id)) {
4704
4705                    var index;
4706
4707                    if (price_index) {
4708                        index = download_id + '_' + price_index;
4709                    } else {
4710                        index = download_id;
4711                    }
4712
4713                    if (window.pysEddProductData[download_id].hasOwnProperty(index)) {
4714                        if (window.pysEddProductData[download_id][index].hasOwnProperty('ga')) {
4715
4716                            Utils.copyProperties(window.pysEddProductData[download_id][index]['ga'].params, event.params);
4717
4718                            // update items qty param
4719                            event.params.items[0].quantity = qty;
4720
4721                            this.fireEvent(event.name,event);
4722
4723                        }
4724                    }
4725
4726                }
4727
4728            },
4729
4730            onEddRemoveFromCartEvent: function (event) {
4731                this.fireEvent(event.name, event);
4732            },
4733
4734            onPageScroll: function (event) {
4735                if (initialized && this.isEnabled()) {
4736                    this.fireEvent(event.name, event);
4737                }
4738            },
4739            onTime: function (event) {
4740                if (initialized && this.isEnabled()) {
4741                    this.fireEvent(event.name, event);
4742                }
4743            },
4744        };
4745
4746    }(options);
4747
4748    var GAds = function (options) {
4749
4750        var initialized = false;
4751        var isAllowEnhancedConversions = false
4752        /**
4753         * Fires event
4754         *
4755         * @link: https://developers.google.com/analytics/devguides/collection/gtagjs/sending-data
4756         * @link: https://developers.google.com/analytics/devguides/collection/gtagjs/events
4757         * @link: https://developers.google.com/gtagjs/reference/event
4758         * @link: https://developers.google.com/gtagjs/reference/parameter
4759         */
4760        function fireEvent(name, data) {
4761            if(typeof window.pys_event_data_filter === "function" && window.pys_disable_event_filter(event_name,'google_ads')) {
4762                return;
4763            }
4764            var _params = Utils.copyProperties(data.params,{});
4765
4766            _params.event_id = Utils.generateUniqueId(data);
4767
4768            var ids = data.ids.filter(function (pixelId) {
4769                return !Utils.hideMatchingPixel(pixelId, 'google_ads');
4770            });
4771
4772            var conversionIds = data.hasOwnProperty('conversion_ids') ? data.conversion_ids.filter(function (conversion_id) {
4773                return !Utils.hideMatchingPixel(conversion_id, 'google_ads');
4774            }) : [];
4775            var conversion_labels = data.hasOwnProperty('conversion_labels') ? data.conversion_labels.filter(function (conversion_label) {
4776                conversion_id = conversion_label.split('/')[0];
4777                return !Utils.hideMatchingPixel(conversion_id, 'google_ads');
4778            }) : [];
4779
4780            Utils.copyProperties(Utils.getRequestParams(), _params);
4781            var _fireEvent = function (conversion_id,event_name) {
4782
4783                params = Utils.copyProperties(_params, { send_to: conversion_id });
4784
4785                if("conversion" === event_name) {
4786                    delete params.items;
4787                    delete params.ecomm_pagetype;
4788                    delete params.ecomm_prodid;
4789                    delete params.ecomm_totalvalue;
4790                }
4791
4792                if (options.debug) {
4793                    console.log('[Google Ads #' + conversion_id + '] ' + event_name, params);
4794                }
4795                gtag('event', event_name, params);
4796                var customEvent = new CustomEvent('gtag_event_sent', {
4797                    detail: {
4798                        eventName: event_name,
4799                        params: params,
4800                        pixel_ids: conversion_id
4801                    }
4802                });
4803                window.dispatchEvent(customEvent);
4804
4805            };
4806
4807
4808            if ( conversion_labels.length > 0 ) {
4809                ids = conversion_labels;
4810                if ( !isTrackEventForGA.includes( name ) ) {
4811                    _fireEvent( ids, name );
4812                }
4813            } else {
4814                var conversion_event_name = data.e_id;
4815                switch ( conversion_event_name ) {
4816                    case "woo_add_to_cart_on_cart_page":
4817                    case "woo_add_to_cart_on_checkout_page":
4818                    case "woo_add_to_cart_on_button_click":
4819                        conversion_event_name = 'woo_add_to_cart';
4820                        break;
4821                    case "edd_add_to_cart_on_cart_page":
4822                    case "edd_add_to_cart_on_checkout_page":
4823                    case "edd_add_to_cart_on_button_click":
4824                        conversion_event_name = 'edd_add_to_cart';
4825                        break;
4826                    case "automatic_event_adsense":
4827                    case "automatic_event_comment":
4828                    case "automatic_event_download":
4829                    case "automatic_event_email_link":
4830                    case "automatic_event_form":
4831                    case "automatic_event_internal_link":
4832                    case "automatic_event_outbound_link":
4833                    case "automatic_event_scroll":
4834                    case "automatic_event_tel_link":
4835                    case "automatic_event_time_on_page":
4836                    case "automatic_event_video":
4837                        conversion_event_name = 'automatic_event';
4838                        break;
4839                }
4840
4841                if ( ids.length ) {
4842                    if ( conversion_event_name !== 'automatic_event' && options.hasOwnProperty('google_ads') && options.google_ads[ conversion_event_name + '_conversion_track' ] ) {
4843                        const conversionTrack = options.google_ads[ conversion_event_name + '_conversion_track' ];
4844
4845                        if ( conversionTrack === 'conversion' ) {
4846                            _fireEvent( ids, "conversion" );
4847                            ids = conversionIds;
4848                        }
4849                    }
4850                } else {
4851                    ids = conversionIds;
4852                }
4853
4854                if ( !isTrackEventForGA.includes( name ) ) {
4855                    _fireEvent( ids, name );
4856                }
4857            }
4858        }
4859
4860        function normalizeEventName(eventName) {
4861
4862            var matches = {
4863                ViewContent: 'view_item',
4864                AddToCart: 'add_to_cart',
4865                AddToWishList: 'add_to_wishlist',
4866                InitiateCheckout: 'begin_checkout',
4867                Purchase: 'purchase',
4868                Lead: 'generate_lead',
4869                CompleteRegistration: 'sign_up',
4870                AddPaymentInfo: 'set_checkout_option'
4871            };
4872
4873            return matches.hasOwnProperty(eventName) ? matches[eventName] : eventName;
4874
4875        }
4876
4877        /**
4878         * Public API
4879         */
4880        return {
4881            tag: function() {
4882                return "google_ads";
4883            },
4884            isEnabled: function () {
4885                return options.hasOwnProperty('google_ads');
4886            },
4887            getHidePixel: function(){
4888                if(this.isEnabled() && options.google_ads.hasOwnProperty('hide_pixels'))
4889                {
4890                    return options.google_ads.hide_pixels;
4891                }
4892                return [];
4893            },
4894            disable: function () {
4895                initialized = false;
4896            },
4897
4898            updateEnhancedConversionData : function () {
4899
4900                if(options.hasOwnProperty("tracking_analytics") && options.tracking_analytics.hasOwnProperty("userDataEnable") && options.tracking_analytics.userDataEnable){
4901                    var advanced = Utils.getAdvancedMergeFormData()
4902                    gtag('set', 'user_data', advanced);
4903                }
4904            },
4905
4906            loadPixel: function () {
4907
4908                if (initialized || !this.isEnabled() || !Utils.consentGiven('google_ads')) {
4909                    return;
4910                }
4911                var ids = options.google_ads.conversion_ids.filter(function (pixelId) {
4912                    return !Utils.hideMatchingPixel(pixelId, 'google_ads');
4913                });
4914                loadTags.push(...ids);
4915                if(!isAdsLoad && options.google_ads.conversion_ids.length > 0){
4916                    for (var i = 0; i < options.google_ads.conversion_ids.length; i++) {
4917                        var trackingId = options.google_ads.conversion_ids[i];
4918                        if (!Utils.hideMatchingPixel(trackingId, 'google_ads')) {
4919                            Utils.loadGoogleTag(trackingId);
4920                            break;
4921                        }
4922                    }
4923
4924                    // configure conversion ids
4925                    ids.forEach(function (conversion_id,index) {
4926
4927                        let config = {};
4928
4929                        if(options.google_ads.enhanced_conversion.includes("index_"+index)) {
4930                            isAllowEnhancedConversions = true;
4931                            config.allow_enhanced_conversions = true
4932                        }
4933
4934                        // Cross-Domain tracking
4935                        if (options.google_ads.crossDomainEnabled) {
4936                            config.linker = {
4937                                accept_incoming: options.google_ads.crossDomainAcceptIncoming,
4938                                domains: options.google_ads.crossDomainDomains
4939                            };
4940                        }
4941
4942                        gtag('config', conversion_id, config );
4943
4944                        if(options.hasOwnProperty("tracking_analytics") && options.tracking_analytics.hasOwnProperty("userDataEnable") && options.tracking_analytics.userDataEnableuserDataEnable){
4945                            var advanced = Utils.getAdvancedMergeFormData()
4946                            gtag('set', 'user_data', advanced);
4947                        }
4948
4949                    });
4950                    isAdsLoad = true;
4951                }
4952
4953                initialized = true;
4954
4955                Utils.fireStaticEvents('google_ads');
4956
4957            },
4958
4959            fireEvent: function (name, data) {
4960
4961                if (!initialized || !this.isEnabled()) {
4962                    return false;
4963                }
4964
4965                data.delay = data.delay || 0;
4966                data.params = data.params || {};
4967                data.ids = data.ids || [];
4968                data.conversion_labels = data.conversion_labels || [];
4969
4970                if (data.delay === 0) {
4971                    fireEvent(name, data);
4972                } else {
4973                    setTimeout(function (name, data) {
4974                        fireEvent(name, data);
4975                    }, data.delay * 1000, name, data);
4976                }
4977
4978                return true;
4979
4980            },
4981
4982            onAdSenseEvent: function (event) {
4983                this.fireEvent(event.name, event);
4984            },
4985
4986            onClickEvent: function (action, params) {
4987                //disabled
4988            },
4989
4990            onWatchVideo: function (event) {
4991                this.fireEvent(event.name, event);
4992            },
4993
4994            onCommentEvent: function (event) {
4995                this.fireEvent(event.name, event);
4996            },
4997
4998            onFormEvent: function (event) {
4999                this.fireEvent(event.name, event);
5000            },
5001
5002            onDownloadEvent: function (event) {
5003                this.fireEvent(event.name, event);
5004            },
5005
5006
5007
5008
5009            onWooAddToCartOnButtonEvent: function (product_id) {
5010
5011                if(!options.dynamicEvents.woo_add_to_cart_on_button_click.hasOwnProperty(this.tag()))
5012                    return;
5013
5014                if (window.pysWooProductData.hasOwnProperty(product_id)) {
5015                    if (window.pysWooProductData[product_id].hasOwnProperty('google_ads')) {
5016
5017                        var event = Utils.clone(options.dynamicEvents.woo_add_to_cart_on_button_click[this.tag()])
5018                        Utils.copyProperties(window.pysWooProductData[product_id]['google_ads']['params'].params, event.params)
5019                        event["ids"] = window.pysWooProductData[product_id]['google_ads']['ids']
5020                        event["conversion_labels"] = window.pysWooProductData[product_id]['google_ads']['conversion_labels']
5021                        this.fireEvent(event.name, event);
5022                    }
5023                }
5024
5025            },
5026
5027            onWooAddToCartOnSingleEvent: function (product_id, qty, product_type, is_external, $form) {
5028
5029                window.pysWooProductData = window.pysWooProductData || [];
5030                if(!options.dynamicEvents.woo_add_to_cart_on_button_click.hasOwnProperty(this.tag()))
5031                    return;
5032                var event = Utils.clone(options.dynamicEvents.woo_add_to_cart_on_button_click[this.tag()]);
5033
5034                if (product_type === Utils.PRODUCT_VARIABLE && !options.google_ads.wooVariableAsSimple) {
5035                    product_id = parseInt($form.find('input[name="variation_id"]').val());
5036                }
5037
5038                if (window.pysWooProductData.hasOwnProperty(product_id)) {
5039                    if (window.pysWooProductData[product_id].hasOwnProperty('google_ads')) {
5040
5041                        Utils.copyProperties(window.pysWooProductData[product_id]['google_ads']["params"], event.params);
5042                        event["ids"] = window.pysWooProductData[product_id]['google_ads']['ids']
5043                        event["conversion_labels"] = window.pysWooProductData[product_id]['google_ads']['conversion_labels']
5044
5045                        var groupValue = 0;
5046                        if(product_type === Utils.PRODUCT_GROUPED ) {
5047                            $form.find(".woocommerce-grouped-product-list .qty").each(function(index){
5048                                var childId = $(this).attr('name').replaceAll("quantity[","").replaceAll("]","");
5049                                var quantity = parseInt($(this).val());
5050                                if(isNaN(quantity)) {
5051                                    quantity = 0;
5052                                }
5053
5054                                var childItem = window.pysWooProductData[product_id]['google_ads'].grouped[childId];
5055
5056                                if(options.woo.addToCartOnButtonValueEnabled &&
5057                                    options.woo.addToCartOnButtonValueOption !== 'global') {
5058
5059                                    event.params.items.forEach(function(el,index,array) {
5060                                        if(el.id == childItem.content_id) {
5061                                            if(quantity > 0){
5062                                                el.quantity = quantity;
5063                                                el.price = childItem.price;
5064                                            } else {
5065                                                array.splice(index, 1);
5066                                            }
5067                                        }
5068                                    });
5069                                }
5070                                groupValue += childItem.price * quantity;
5071                            });
5072                            if(groupValue == 0) return;
5073                            event.params.value = groupValue;
5074                        } else {
5075                            // update items qty param
5076                            event.params.items[0].quantity = qty;
5077                        }
5078
5079
5080
5081                        // maybe customize value option
5082                        if (options.woo.addToCartOnButtonValueEnabled &&
5083                            options.woo.addToCartOnButtonValueOption !== 'global' &&
5084                            product_type !== Utils.PRODUCT_GROUPED) {
5085                            event.params.value =  event.params.value * qty;
5086                        }
5087
5088
5089
5090                        var eventName = is_external ? options.woo.affiliateEventName : event.name;
5091                        eventName = normalizeEventName(eventName);
5092
5093                        this.fireEvent(eventName, event);
5094
5095                    }
5096                }
5097
5098            },
5099
5100            onWooRemoveFromCartEvent: function (event) {
5101                this.fireEvent(event.name, event);
5102            },
5103
5104            onWooAffiliateEvent: function (product_id) {
5105                if(!options.dynamicEvents.woo_affiliate.hasOwnProperty(this.tag()))
5106                    return;
5107                var event = options.dynamicEvents.woo_affiliate[this.tag()];
5108
5109                if (window.pysWooProductData.hasOwnProperty(product_id)) {
5110                    if (window.pysWooProductData[product_id].hasOwnProperty('google_ads')) {
5111
5112                        event = Utils.clone(event)
5113                        Utils.copyProperties(window.pysWooProductData[product_id][this.tag()], event.params)
5114                        this.fireEvent(normalizeEventName(options.woo.affiliateEventName), event);
5115
5116                    }
5117                }
5118
5119            },
5120
5121            onWooPayPalEvent: function (event) {
5122                this.fireEvent(event.name, event);
5123            },
5124
5125            onEddAddToCartOnButtonEvent: function (download_id, price_index, qty) {
5126                if(!options.dynamicEvents.edd_add_to_cart_on_button_click.hasOwnProperty(this.tag()))
5127                    return;
5128                var event = options.dynamicEvents.edd_add_to_cart_on_button_click[this.tag()];
5129
5130
5131                if (window.pysEddProductData.hasOwnProperty(download_id)) {
5132
5133                    var index;
5134
5135                    if (price_index) {
5136                        index = download_id + '_' + price_index;
5137                    } else {
5138                        index = download_id;
5139                    }
5140
5141                    if (window.pysEddProductData[download_id].hasOwnProperty(index)) {
5142                        if (window.pysEddProductData[download_id][index].hasOwnProperty('google_ads')) {
5143
5144                            event = Utils.clone(event)
5145                            Utils.copyProperties(window.pysEddProductData[download_id][index]['google_ads']['params'], event.params);
5146                            event.ids = window.pysEddProductData[download_id][index]['google_ads']['ids']
5147                            // update items qty param
5148                            //params.items[0].quantity = qty;
5149
5150                            this.fireEvent(event.name, event);
5151
5152                        }
5153                    }
5154
5155                }
5156
5157            },
5158
5159            onEddRemoveFromCartEvent: function (event) {
5160                this.fireEvent(event.name, event);
5161            },
5162            onPageScroll: function (event) {
5163                if (initialized && this.isEnabled()) {
5164                    this.fireEvent(event.name, event);
5165                }
5166            },
5167            onTime: function (event) {
5168                if (initialized && this.isEnabled()) {
5169                    this.fireEvent(event.name, event);
5170                }
5171            },
5172
5173        };
5174
5175    }(options);
5176
5177    var GTM = function (options) {
5178
5179        var initialized = false;
5180
5181        var datalayer_name = 'dataLayer';
5182        /*
5183         * @param name
5184         * @param data
5185         */
5186        function fireEvent(name, event) {
5187            if(typeof window.pys_event_data_filter === "function" && window.pys_disable_event_filter(name,'gtm')) {
5188                return;
5189            }
5190
5191
5192            var eventParams = event.params;
5193            var data = event.params;
5194            var valuesArray = Object.values(event.trackingIds);
5195            var ids = valuesArray.filter(function (pixelId) {
5196                return !Utils.hideMatchingPixel(pixelId, 'gtm');
5197            })
5198            Utils.copyProperties(Utils.getRequestParams(), eventParams);
5199            var _fireEvent = function (tracking_id,name,params, event=null) {
5200
5201                var eventData = {};
5202                var ContainerCodeHasTag = !options.gtm.gtm_just_data_layer && tracking_id.length > 0;
5203                if(ContainerCodeHasTag) {
5204                    params['send_to'] = tracking_id;
5205                }
5206                else if(!options.gtm.gtm_just_data_layer){
5207                    return
5208                }
5209
5210                if (params.hasOwnProperty('ecommerce')) {
5211                    eventData.ecommerce = params.ecommerce;
5212                    delete params.ecommerce;
5213                }
5214
5215                var automatedParams = { ...params };
5216                [params['manualName'], 'manualName', 'triggerType'].forEach(key => delete automatedParams[key]);
5217                if(event && (!event.hasOwnProperty('hasAutoParam') || (event.hasOwnProperty('hasAutoParam') && event.hasAutoParam))) {
5218                    eventData.automatedParameters = automatedParams;
5219                }
5220
5221// Move custom parameters to eventData
5222
5223                if (params.hasOwnProperty(params['manualName'])) {
5224                    eventData[params['manualName']] = params[params['manualName']];
5225                    delete params[params['manualName']];
5226                }
5227
5228                ['manualName','triggerType'].forEach(key => {
5229                    if (params.hasOwnProperty(key)) {
5230                        eventData[key] = params[key];
5231                        delete params[key];
5232                    }
5233                });
5234
5235                eventData.manualDataLayer = options.gtm.gtm_dataLayer_name ?? 'dataLayer';
5236
5237                eventData.event = name;
5238
5239                if (options.debug) {
5240                    if (ContainerCodeHasTag){
5241                        console.log('[Google GTM #' + tracking_id + '] ' + name, eventData);
5242                    }
5243                    else {
5244                        console.log('[Google GTM push to "'+datalayer_name+'"] ' + name, eventData);
5245                    }
5246                }
5247                window[datalayer_name].push(eventData);
5248
5249                var customEvent = new CustomEvent('gtm_event_sent', {
5250                    detail: {
5251                        eventName: name,
5252                        params: eventData,
5253                        pixel_ids: tracking_id
5254                    }
5255                });
5256                window.dispatchEvent(customEvent);
5257
5258            };
5259
5260            var copyParams = Utils.copyProperties(eventParams, {}); // copy params because mapParamsToGTM can modify it
5261
5262            var params = mapParamsToGTM(ids,name,copyParams)
5263
5264            params.event_id = Utils.generateUniqueId(event);
5265
5266            _fireEvent(ids, name, params, event);
5267        }
5268
5269        function normalizeEventName(eventName) {
5270
5271            var matches = {
5272                ViewContent: 'view_item',
5273                AddToCart: 'add_to_cart',
5274                AddToWishList: 'add_to_wishlist',
5275                InitiateCheckout: 'begin_checkout',
5276                Purchase: 'purchase',
5277                Lead: 'generate_lead',
5278                CompleteRegistration: 'sign_up',
5279                AddPaymentInfo: 'set_checkout_option'
5280            };
5281
5282            return matches.hasOwnProperty(eventName) ? matches[eventName] : eventName;
5283
5284        }
5285
5286        function mapParamsToGTM(tag,name,param) {
5287            var hasGTM = false;
5288
5289            // end
5290            if (Array.isArray(tag)) {
5291                hasGTM = tag.some(function (element) {
5292                    return isGTM(element);
5293                });
5294            } else if(isGTM(tag)) {
5295                hasGTM = true;
5296            }
5297            if(hasGTM) {
5298                delete param.event_category;
5299                delete param.event_label;
5300
5301                delete param.analytics_storage;
5302                delete param.ad_storage;
5303                delete param.ad_user_data;
5304                delete param.ad_personalization;
5305
5306                if(name === 'search') {
5307                    param['search'] = param.search_term;
5308                    delete param.search_term;
5309                    delete param.dynx_itemid;
5310                    delete param.dynx_pagetype;
5311                    delete param.dynx_totalvalue;
5312                }
5313            }
5314            return param;
5315        }
5316
5317        function isGTM(tag) {
5318            return tag.indexOf('GTM') === 0;
5319        }
5320        /**
5321         * Public API
5322         */
5323        return {
5324            tag: function() {
5325                return "gtm";
5326            },
5327            isEnabled: function () {
5328                return options.hasOwnProperty('gtm');
5329            },
5330            getHidePixel: function(){
5331                if(this.isEnabled() && options.gtm.hasOwnProperty('hide_pixels'))
5332                {
5333                    return options.gtm.hide_pixels;
5334                }
5335                return [];
5336            },
5337            disable: function () {
5338                initialized = false;
5339            },
5340            updateEnhancedConversionData : function () {
5341                if (!initialized || !this.isEnabled()) {
5342                    return;
5343                }
5344                if(options.hasOwnProperty("tracking_analytics") && options.tracking_analytics.hasOwnProperty("userDataEnable") && options.tracking_analytics.userDataEnable) {
5345                    var advanced = Utils.getAdvancedMergeFormData(true);
5346                    if (Object.keys(advanced).length > 0) {
5347                        window[datalayer_name].push({'user_data' : advanced});
5348                    }
5349                }
5350            },
5351            loadPixel: function () {
5352
5353                if (initialized || !this.isEnabled() || !Utils.consentGiven('analytics')) {
5354                    return;
5355                }
5356                datalayer_name = options.gtm.gtm_dataLayer_name ?? 'dataLayer';
5357
5358                for (var i = 0; i < options.gtm.trackingIds.length; i++) {
5359                    var trackingId = options.gtm.trackingIds[i];
5360                    if (!Utils.hideMatchingPixel(trackingId, 'gtm') && !options.gtm.gtm_just_data_layer) {
5361                        console.log('[PYS] Google Tag Manager container code loaded');
5362                        Utils.loadGTMScript(trackingId);
5363                        break;
5364                    }
5365                }
5366
5367                if(options.gtm.gtm_just_data_layer) {
5368                    console.warn && console.warn("[PYS] Google Tag Manager container code placement set to OFF !!!");
5369                    console.warn && console.warn("[PYS] Data layer codes are active but GTM container must be loaded using custom coding !!!");
5370                    if(options.gtm.trackingIds.length == 0){
5371                        Utils.loadGTMScript();
5372                    }
5373                }
5374
5375                if(options.hasOwnProperty("tracking_analytics") && options.tracking_analytics.hasOwnProperty("userDataEnable") && options.tracking_analytics.userDataEnable){
5376                    var advanced = Utils.getAdvancedMergeFormData(true);
5377                    if(Object.keys(advanced).length > 0){
5378                        window[datalayer_name].push({'user_data' : advanced});
5379                    }
5380                }
5381
5382
5383                var config = {};
5384
5385                if(options.user_id && options.user_id != 0) {
5386                    config.user_id = options.user_id;
5387                }
5388
5389                // Cross-Domain tracking
5390
5391                var ids = options.gtm.trackingIds.filter(function (pixelId) {
5392                    return !Utils.hideMatchingPixel(pixelId, 'gtm');
5393                });
5394
5395
5396                initialized = true;
5397
5398                Utils.fireStaticEvents('gtm');
5399            },
5400
5401            fireEvent: function (name, data) {
5402
5403                if (!initialized || !this.isEnabled()) {
5404                    return false;
5405                }
5406
5407                data.delay = data.delay || 0;
5408                data.params = data.params || {};
5409
5410                if (data.delay === 0) {
5411
5412                    fireEvent(name, data);
5413
5414                } else {
5415
5416                    setTimeout(function (name, params) {
5417                        fireEvent(name, params);
5418                    }, data.delay * 1000, name, data);
5419
5420                }
5421
5422                return true;
5423
5424            },
5425
5426            onAdSenseEvent: function (event) {
5427                this.fireEvent(event.name, event);
5428            },
5429
5430            onClickEvent: function (event) {
5431                this.fireEvent(event.name, event);
5432            },
5433
5434            onWatchVideo: function (event) {
5435                if(!event.hasOwnProperty("youtube_disabled")
5436                    || !event.youtube_disabled
5437                    || event.params.video_type !== "youtube") {
5438                    this.fireEvent(event.name, event);
5439                }
5440            },
5441
5442            onCommentEvent: function (event) {
5443
5444                this.fireEvent(event.name, event);
5445
5446            },
5447
5448            onFormEvent: function (event) {
5449
5450                this.fireEvent(event.name, event);
5451
5452            },
5453
5454            onDownloadEvent: function (event) {
5455
5456                this.fireEvent(event.name, event);
5457
5458            },
5459
5460            onWooAddToCartOnButtonEvent: function (product_id, prod_info = null) {
5461                if(!options.dynamicEvents.woo_add_to_cart_on_button_click.hasOwnProperty(this.tag()))
5462                    return;
5463                if (window.pysWooProductData.hasOwnProperty(product_id)) {
5464                    if (window.pysWooProductData[product_id].hasOwnProperty('gtm')) {
5465                        var event = Utils.clone(options.dynamicEvents.woo_add_to_cart_on_button_click[this.tag()]);
5466                        Utils.copyProperties(window.pysWooProductData[product_id]['gtm'].params, event.params)
5467                        event.trackingIds = window.pysWooProductData[product_id]['gtm']['trackingIds'];
5468
5469
5470                        if(prod_info)
5471                        {
5472                            item = event.params.hasOwnProperty('ecommerce') ? event.params.ecommerce.items[0] : event.params.items[0];
5473
5474                            if(prod_info['pys_list_name_productlist_id'])
5475                            {
5476                                item['item_list_id'] = prod_info['pys_list_name_productlist_id']
5477                            }
5478                            if(prod_info['pys_list_name_productlist_name'])
5479                            {
5480                                item['item_list_name'] =prod_info['pys_list_name_productlist_name']
5481                            }
5482                        }
5483                        this.fireEvent(event.name, event);
5484                    }
5485                }
5486
5487            },
5488
5489            onWooAddToCartOnSingleEvent: function (product_id, qty, product_type, is_external, $form, prod_info) {
5490                window.pysWooProductData = window.pysWooProductData || [];
5491
5492                if(!options.dynamicEvents.woo_add_to_cart_on_button_click.hasOwnProperty(this.tag()))
5493                    return;
5494                var event = Utils.clone(options.dynamicEvents.woo_add_to_cart_on_button_click[this.tag()]);
5495
5496                if (product_type === Utils.PRODUCT_VARIABLE && !options.gtm.wooVariableAsSimple) {
5497                    product_id = parseInt($form.find('input[name="variation_id"]').val());
5498                }
5499
5500                if (window.pysWooProductData.hasOwnProperty(product_id)) {
5501                    if (window.pysWooProductData[product_id].hasOwnProperty('gtm')) {
5502
5503                        Utils.copyProperties(window.pysWooProductData[product_id]['gtm'].params, event.params);
5504
5505                        params = event.params.hasOwnProperty('ecommerce') ? event.params.ecommerce : event.params;
5506
5507                        if(product_type === Utils.PRODUCT_GROUPED ) {
5508                            var groupValue = 0;
5509                            $form.find(".woocommerce-grouped-product-list .qty").each(function(index){
5510                                var childId = $(this).attr('name').replaceAll("quantity[","").replaceAll("]","");
5511                                var quantity = parseInt($(this).val());
5512                                if(isNaN(quantity)) {
5513                                    quantity = 0;
5514                                }
5515                                var childItem = window.pysWooProductData[product_id]['gtm'].grouped[childId];
5516
5517                                params.items.forEach(function(el,index,array) {
5518                                    if(el.id == childItem.content_id) {
5519                                        if(quantity > 0){
5520                                            el.quantity = quantity;
5521                                            el.price = childItem.price;
5522                                        } else {
5523                                            array.splice(index, 1);
5524                                        }
5525                                    }
5526                                });
5527                                groupValue += childItem.price * quantity;
5528                            });
5529
5530
5531
5532                            if(options.woo.addToCartOnButtonValueEnabled &&
5533                                options.woo.addToCartOnButtonValueOption !== 'global' &&
5534                                params.hasOwnProperty('value')) {
5535                                params.value = groupValue;
5536                            }
5537
5538                            if(groupValue == 0) return; // skip if no items selected
5539                        } else {
5540                            // update items qty param
5541                            params.items[0].quantity = qty;
5542                        }
5543
5544                        // maybe customize value option
5545                        if (options.woo.addToCartOnButtonValueEnabled &&
5546                            options.woo.addToCartOnButtonValueOption !== 'global' &&
5547                            product_type !== Utils.PRODUCT_GROUPED)
5548                        {
5549                            if(params.hasOwnProperty('value')) {
5550                                params.value = params.items[0].price * qty;
5551                            }
5552                        }
5553
5554                        if(prod_info)
5555                        {
5556                            if(prod_info['pys_list_name_productlist_id'])
5557                            {
5558                                params.items[0]['item_list_id'] = prod_info['pys_list_name_productlist_id']
5559                            }
5560                            if(prod_info['pys_list_name_productlist_name'])
5561                            {
5562                                params.items[0]['item_list_name'] =prod_info['pys_list_name_productlist_name']
5563                            }
5564                        }
5565
5566                        var eventName = is_external ? options.woo.affiliateEventName : event.name;
5567                        eventName = normalizeEventName(eventName);
5568
5569                        this.fireEvent(eventName, event);
5570
5571                    }
5572                }
5573
5574            },
5575
5576            onWooCheckoutProgressStep: function (event) {
5577                this.fireEvent(event.name, event);
5578            },
5579
5580            onWooSelectContent: function (event) {
5581                const select_prod_list = {};
5582
5583                if (event.params.items[0].item_list_name !== undefined) {
5584                    select_prod_list.list_name = event.params.items[0].item_list_name;
5585                }
5586
5587                if (event.params.items[0].item_list_id !== undefined) {
5588                    select_prod_list.list_id = event.params.items[0].item_list_id;
5589                }
5590                const url = new URL(window.location.href);
5591                select_prod_list.url = url.origin + url.pathname;
5592                Cookies.set('select_prod_list', JSON.stringify(select_prod_list), { expires: 1,path: '/' });
5593                this.fireEvent(event.name, event);
5594            },
5595
5596            onWooRemoveFromCartEvent: function (event) {
5597                this.fireEvent(event.name, event);
5598            },
5599
5600            onWooAffiliateEvent: function (product_id) {
5601                if(!options.dynamicEvents.woo_affiliate.hasOwnProperty(this.tag()))
5602                    return;
5603                var event = options.dynamicEvents.woo_affiliate[this.tag()];
5604
5605                if (window.pysWooProductData.hasOwnProperty(product_id)) {
5606                    if (window.pysWooProductData[product_id].hasOwnProperty('gtm')) {
5607
5608                        event = Utils.clone(event );
5609                        Utils.copyProperties(window.pysWooProductData[product_id][this.tag()], event.params)
5610                        this.fireEvent(normalizeEventName(options.woo.affiliateEventName), event);
5611
5612                    }
5613                }
5614
5615            },
5616
5617            onWooPayPalEvent: function (event) {
5618                this.fireEvent(event.name, event);
5619            },
5620
5621            onEddAddToCartOnButtonEvent: function (download_id, price_index, qty) {
5622                if(!options.dynamicEvents.edd_add_to_cart_on_button_click.hasOwnProperty(this.tag()))
5623                    return;
5624                var event = Utils.clone(options.dynamicEvents.edd_add_to_cart_on_button_click[this.tag()]);
5625
5626
5627                if (window.pysEddProductData.hasOwnProperty(download_id)) {
5628
5629                    var index;
5630
5631                    if (price_index) {
5632                        index = download_id + '_' + price_index;
5633                    } else {
5634                        index = download_id;
5635                    }
5636
5637                    if (window.pysEddProductData[download_id].hasOwnProperty(index)) {
5638                        if (window.pysEddProductData[download_id][index].hasOwnProperty('gtm')) {
5639
5640                            Utils.copyProperties(window.pysEddProductData[download_id][index]['gtm'].params, event.params);
5641                            item = event.params.hasOwnProperty('ecommerce') ? event.params.ecommerce.items[0] : event.params.items[0];
5642                            // update items qty param
5643                            item.quantity = qty;
5644
5645                            this.fireEvent(event.name,event);
5646
5647                        }
5648                    }
5649
5650                }
5651
5652            },
5653
5654            onEddRemoveFromCartEvent: function (event) {
5655                this.fireEvent(event.name, event);
5656            },
5657
5658            onPageScroll: function (event) {
5659                if (initialized && this.isEnabled()) {
5660                    this.fireEvent(event.name, event);
5661                }
5662            },
5663            onTime: function (event) {
5664                if (initialized && this.isEnabled()) {
5665                    this.fireEvent(event.name, event);
5666                }
5667            },
5668        };
5669
5670    }(options);
5671
5672    var getPixelBySlag = function getPixelBySlag(slug) {
5673        switch (slug) {
5674            case "facebook": return window.pys.Facebook;
5675            case "ga": return window.pys.Analytics;
5676            case "gtm": return window.pys.GTM;
5677            case "google_ads": return window.pys.GAds;
5678            case "bing": return window.pys.Bing;
5679            case "pinterest": return window.pys.Pinterest;
5680            case "tiktok": return window.pys.TikTok;
5681        }
5682    }
5683
5684    window.pys = window.pys || {};
5685    window.pys.Facebook = Facebook;
5686    window.pys.Analytics = Analytics;
5687    window.pys.GAds = GAds;
5688    window.pys.GTM = GTM;
5689    window.pys.Utils = Utils;
5690    window.pys.TikTok = TikTok;
5691    window.pys.getPixelBySlag = getPixelBySlag;
5692    
5693    // Export getPixelBySlag globally for backward compatibility
5694    window.getPixelBySlag = getPixelBySlag;
5695
5696
5697
5698    $(document).ready(function () {
5699
5700        if(Cookies.get('form_track'))
5701        {
5702            Cookies.remove('form_track')
5703        }
5704
5705        if($("#pys_late_event").length > 0) {
5706            var dirAttr = $("#pys_late_event").attr("dir");
5707            if (dirAttr) {
5708                try {
5709                    var events = JSON.parse(dirAttr);
5710                } catch (e) {
5711                    console.warn("Invalid JSON in pys_late_event dir attribute:", e);
5712                }
5713            } else {
5714                console.warn("pys_late_event dir attribute is undefined or empty");
5715            }
5716            if (events) {
5717                for (var platform in events) {
5718                    if (events.hasOwnProperty(platform)) {
5719                        var platformEvents = events[platform];
5720                        platformEvents.forEach(function (event) {
5721                            var eventData = {};
5722                            eventData[event.e_id] = [event];
5723                            if (options.staticEvents.hasOwnProperty(platform)) {
5724                                Object.assign(options.staticEvents[platform], eventData);
5725                            } else {
5726                                options.staticEvents[platform] = eventData;
5727                            }
5728                        });
5729                    }
5730                }
5731            }
5732        }
5733
5734        var Pinterest = Utils.setupPinterestObject();
5735        var Bing = Utils.setupBingObject();
5736        if(options.hasOwnProperty('cookie'))
5737        {
5738            if(options.cookie.externalID_disabled_by_api || options.cookie.disabled_all_cookie)
5739            {
5740                Cookies.remove('pbid')
5741            }
5742            if(options.cookie.disabled_advanced_form_data_cookie || options.cookie.disabled_all_cookie)
5743            {
5744                Cookies.remove('pys_advanced_form_data')
5745            }
5746
5747            if(options.cookie.disabled_landing_page_cookie || !options.enable_lading_page_param || options.cookie.disabled_all_cookie)
5748            {
5749                Cookies.remove('pys_landing_page', { path: '/',domain: domain })
5750                Cookies.remove('last_pys_landing_page', { path: '/',domain: domain })
5751            }
5752            if(options.cookie.disabled_trafficsource_cookie || options.cookie.disabled_all_cookie)
5753            {
5754                Cookies.remove('pysTrafficSource', { path: '/',domain: domain })
5755                Cookies.remove('last_pysTrafficSource', { path: '/',domain: domain })
5756            }
5757            if(options.cookie.disabled_first_visit_cookie || options.cookie.disabled_all_cookie)
5758            {
5759                Cookies.remove('pys_first_visit', { path: '/',domain: domain })
5760
5761            }
5762            if(options.cookie.disabled_utmTerms_cookie || options.cookie.disabled_all_cookie)
5763            {
5764                $.each(Utils.utmTerms, function (index, name) {
5765                    Cookies.remove('pys_' + name, { path: '/',domain: domain })
5766                });
5767                $.each(Utils.utmTerms, function (index, name) {
5768                    Cookies.remove('last_pys_' + name, { path: '/',domain: domain })
5769                });
5770            }
5771            if(options.cookie.disabled_utmId_cookie || options.cookie.disabled_all_cookie)
5772            {
5773                $.each(Utils.utmId,function(index,name) {
5774                    Cookies.remove('pys_' + name, { path: '/',domain: domain })
5775                })
5776                $.each(Utils.utmId,function(index,name) {
5777                    Cookies.remove('last_pys_' + name, { path: '/',domain: domain })
5778                });
5779            }
5780        }
5781
5782        if (options.gdpr.cookie_law_info_integration_enabled) {
5783            var cli_cookie = Cookies.get('cookieyes-consent') ?? Cookies.get('wt_consent') ?? Cookies.get('viewed_cookie_policy');
5784
5785            if (typeof cli_cookie !== 'undefined') {
5786                if (cli_cookie === Cookies.get('cookieyes-consent') || cli_cookie === Cookies.get('wt_consent')) {
5787                    if (getCookieYes('analytics') === 'yes') {
5788                        Utils.manageCookies();
5789                    }
5790                } else if (cli_cookie === Cookies.get('viewed_cookie_policy') && cli_cookie == 'yes') {
5791                    Utils.manageCookies();
5792                }
5793            }
5794        }
5795
5796        if ( options.gdpr.consent_magic_integration_enabled && typeof CS_Data !== "undefined" ) {
5797            if ( CS_Data.cs_script_cat.pys == CS_Data.cs_necessary_cat_id || CS_Data.cs_script_cat.pys == 0 ) {
5798                Utils.manageCookies();
5799            } else if ( Cookies.get( 'cs_enabled_cookie_term' + CS_Data.test_prefix + '_' + CS_Data.cs_script_cat.pys ) == 'yes' ) {
5800                Utils.manageCookies();
5801            }
5802        } else {
5803            Utils.manageCookies();
5804        }
5805
5806        Utils.initializeRequestParams();
5807        Utils.setupGdprCallbacks();
5808
5809        if ( options.enable_auto_save_advance_matching ) {
5810            let override = options.data_persistency == 'recent_data';
5811
5812            //Setup Advanced Form Data
5813            if ( options.advance_matching_form.enable_advance_matching_forms ) {
5814                $( document ).on( "blur", "input[type='email']", function () {
5815                    let email = $( this ).val().trim().toLowerCase();
5816                    if ( Utils.validateEmail( email ) ) {
5817                        Utils.saveAdvancedFormData( email, null, null, null, override );
5818                    }
5819                } )
5820                $( document ).on( "blur", "input[type='tel']", function () {
5821                    let phone = $( this ).val().trim().replace( /\D/g, "" );
5822                    if ( phone.length > 5 ) {
5823                        Utils.saveAdvancedFormData( null, phone, null, null, override );
5824                    }
5825                } )
5826                $( document ).on( "blur", "input[type='text']", function () {
5827                    let name;
5828                    if ( $( this ).attr( "name" ) && $( this ).attr( "name" ) != '' ) {
5829                        name = $( this ).attr( "name" ).trim()
5830                    }
5831                    if ( name && options.advance_matching_form.advance_matching_fn_names.includes( name ) ) {
5832                        let value = $( this ).val().trim();
5833                        if ( value.length > 0 ) {
5834                            Utils.saveAdvancedFormData( null, null, value, null, override );
5835                        }
5836                    }
5837                    if ( name && options.advance_matching_form.advance_matching_ln_names.includes( name ) ) {
5838                        let value = $( this ).val().trim();
5839                        if ( value.length > 0 ) {
5840                            Utils.saveAdvancedFormData( null, null, null, value, override );
5841                        }
5842                    }
5843                    if ( name && options.advance_matching_form.advance_matching_tel_names.includes( name ) ) {
5844                        let value = $( this ).val().trim();
5845                        if ( value.length > 0 ) {
5846                            Utils.saveAdvancedFormData( null, value, null, null, override );
5847                        }
5848                    }
5849                    if ( name && options.advance_matching_form.advance_matching_em_names.includes( name ) ) {
5850                        let email = $( this ).val().trim().toLowerCase();
5851
5852                        if ( Utils.validateEmail( email ) ) {
5853                            Utils.saveAdvancedFormData( email, null, null, null, false );
5854                        }
5855                    }
5856                } )
5857            }
5858
5859            //Setup Advanced Url Data
5860            if ( Object.keys( options.advance_matching_url ).length > 0 && options.advance_matching_url.enable_advance_matching_url ) {
5861                const url_params = new URLSearchParams( window.location.search );
5862                url_params.forEach( ( value, key ) => {
5863                    if ( options.advance_matching_url.advance_matching_fn_names.includes( key ) ) {
5864                        Utils.saveAdvancedFormData( null, null, value.trim(), null, override );
5865                    }
5866
5867                    if ( options.advance_matching_url.advance_matching_ln_names.includes( key ) ) {
5868                        Utils.saveAdvancedFormData( null, null, null, value.trim(), override );
5869                    }
5870
5871                    if ( options.advance_matching_url.advance_matching_tel_names.includes( key ) ) {
5872                        Utils.saveAdvancedFormData( null, value.trim(), null, null, override );
5873                    }
5874
5875                    if ( options.advance_matching_url.advance_matching_em_names.includes( key ) ) {
5876                        let email = value.trim().toLowerCase()
5877                        if ( Utils.validateEmail( email ) ) {
5878                            Utils.saveAdvancedFormData( email, null, null, null, override );
5879                        }
5880                    }
5881                } );
5882            }
5883        }
5884
5885        // setup Click Event
5886        if (
5887            options.dynamicEvents.hasOwnProperty("automatic_event_internal_link") ||
5888            options.dynamicEvents.hasOwnProperty("automatic_event_outbound_link") ||
5889            options.dynamicEvents.hasOwnProperty("automatic_event_tel_link") ||
5890            options.dynamicEvents.hasOwnProperty("automatic_event_email_link") ||
5891            options.dynamicEvents.hasOwnProperty("automatic_event_download")
5892        ) {
5893
5894            $(document).onFirst('click', 'a, button, input[type="button"], input[type="submit"]', function (e) {
5895
5896                var $elem = $(this);
5897
5898
5899                // Download
5900                if(options.dynamicEvents.hasOwnProperty("automatic_event_download")) {
5901                    var isFired = false;
5902                    if ($elem.is('a')) {
5903                        var href = $elem.attr('href');
5904                        if (typeof href !== "string") {
5905                            return;
5906                        }
5907                        href = href.trim();
5908                        var extension = Utils.getLinkExtension(href);
5909                        var track_download = false;
5910
5911                        if (extension.length > 0) {
5912
5913                            if(options.dynamicEvents.hasOwnProperty("automatic_event_download") ) {
5914                                var pixels = Object.keys(options.dynamicEvents.automatic_event_download);
5915                                for (var i = 0; i < pixels.length; i++) {
5916                                    var event = Utils.clone(options.dynamicEvents.automatic_event_download[pixels[i]]);
5917                                    var extensions = event.extensions;
5918                                    if (extensions.includes(extension)) {
5919
5920                                        if(pixels[i] == "tiktok") {
5921                                            getPixelBySlag(pixels[i]).fireEvent(event.name, event);
5922                                        } else {
5923                                            if (options.enable_remove_download_url_param) {
5924                                                href = href.split('?')[0];
5925                                            }
5926                                            event.params.download_url = href;
5927                                            event.params.download_type = extension;
5928                                            event.params.download_name = Utils.getLinkFilename(href);
5929                                            getPixelBySlag(pixels[i]).onDownloadEvent(event);
5930                                        }
5931
5932                                        isFired = true;
5933                                    }
5934                                }
5935                            }
5936                        }
5937                    }
5938                    if(isFired) { // prevent duplicate events on the same element
5939                        return;
5940                    }
5941                }
5942
5943
5944                if (!e.hasOwnProperty('originalEvent')) {
5945                    return;
5946                }
5947                if($elem.hasClass("add_to_cart_button") ||
5948                    $elem.hasClass("single_add_to_cart_button") ) { // add_to_cart_button fire in woo
5949                    return;
5950                }
5951
5952                if(options.dynamicEvents.hasOwnProperty("wcf_add_to_cart_on_next_step_click")
5953                    && $elem.hasClass("wcf-next-step-link")) {
5954                    return;// add_to_cart_button fire in woo cf
5955                }
5956                if(options.dynamicEvents.hasOwnProperty("wcf_add_to_cart_on_bump_click")
5957                    && $elem.hasClass("wcf-bump-order-cb")) {
5958                    return;// add_to_cart_button fire in woo cf
5959                }
5960
5961                if($elem.hasClass("remove_from_cart_button") ) { // cancel remove from cart
5962                    return;
5963                }
5964                if($elem.hasClass("remove") ) { // cancel remove from cart
5965                    if($elem.parents('.cart_item').length || $elem.parents('.mini_cart_item').length)
5966                        return;
5967                }
5968                if($elem.attr("name") == "update_cart" || $elem.attr("name") == "apply_coupon") { // cancel update  c
5968art or coupon button
5969                    return;
5970                }
5971
5972
5973                if ($elem.hasClass('pys_block')) {
5974                    return; // avoiding fake double clicks from Affiliate event
5975                }
5976                var text = "";
5977                var target_url = "";
5978                var linkType = "Internal Click";
5979
5980                if ($elem.is('a')) {
5981                    var href = $elem.attr('href');
5982
5983                    // fixes #112
5984                    if (typeof href !== "string") {
5985                        return;
5986                    }
5987                    href = href.trim();
5988
5989                    text = $elem.contents().filter(function() {
5990                        return this.nodeType === 3; // Фильтруем только текстовые узлы
5991                    }).text().trim();
5992                    if(options.enable_remove_target_url_param) {
5993                        target_url = href.split('?')[0];
5994                    } else {
5995                        target_url = href
5996                    }
5997
5998
5999                    //Email Event
6000                    if ( href.startsWith( 'mailto:' ) ) {
6001                        if ( options.triggerEventTypes.hasOwnProperty( "email_link" ) ) {
6002                            return;
6003                        } else {
6004                            setupEmailLinks();
6005                        }
6006
6007                        return; // not fire next
6008                    }
6009
6010                    // Phone
6011                    if (href.startsWith('tel:')) {
6012                        if(options.dynamicEvents.hasOwnProperty("automatic_event_tel_link")) {
6013                            var pixels = Object.keys(options.dynamicEvents.automatic_event_tel_link);
6014                            for(var i = 0;i<pixels.length;i++) {
6015                                var event = Utils.clone(options.dynamicEvents.automatic_event_tel_link[pixels[i]]);
6016                                if ( pixels[i] !== 'tiktok') {
6017                                    Utils.copyProperties(Utils.getRequestParam
6017s(), event.params);
6018                                }
6019                                getPixelBySlag(pixels[i]).fireEvent(event.name, event);
6020                            }
6021                        }
6022                        return; // not fire next
6023                    }
6024
6025                    if (href.startsWith('http')) {
6026                        // link type
6027                        var host = $elem.context != undefined ? $elem.context.host : $elem[0].host;
6028                        if (document.location.host != host) {
6029                            linkType = 'External Click';
6030                        }
6031                    }
6032                } else if ($elem.is('button')) {
6033                    if( $elem.hasClass("forminator-button-submit")) {
6034                        //disable duplicate events
6035                        return;
6036                    }
6037                    text = $elem.contents().filter(function() {
6038                        return this.nodeType === 3; // Фильтруем только текстовые узлы
6039                    }).text().trim();
6040                } else if ($elem.is('input[type="button"]')) {
6041                    text = $elem.val();
6042                } else if ($elem.is('input[type="submit"]')) {
6043                    if ( $elem.parents("form.comment-form")) {
6044                        //disable duplicate events
6045                        return;
6046                    }
6047                    if ($elem.parents("form")) {
6048                        //disable duplicate events
6049                        return;
6050                    }
6051                    text = $elem.val();
6052                } else {
6053                    return;
6054                }
6055
6056
6057
6058                text = Utils.filterEmails(text);
6059
6060
6061                if( linkType === "Internal Click"
6062                    && options.dynamicEvents.hasOwnProperty("automatic_event_internal_link")
6063                ) {
6064                    var pixels = Object.keys(options.dynamicEvents.automatic_event_internal_link);
6065
6066                    for(var i = 0;i<pixels.length;i++) {
6067                        var event = Utils.clone(options.dynamicEvents.automatic_event_internal_link[pixels[i]]);
6068
6069                        if(pixels[i] !== "tiktok") { // TT doesn't support custom parameters
6070                            event.params["text"] = text;
6071                            if(target_url){
6072                                event.params["target_url"] = target_url;
6073                            }
6074                            Utils.copyProperties(Utils.getRequestParam
6074s(), event.params);
6075                        }
6076
6077
6078                        getPixelBySlag(pixels[i]).fireEvent(event.name, event);
6079                    }
6080                }
6081
6082                if( linkType === "External Click"
6083                    && options.dynamicEvents.hasOwnProperty("automatic_event_outbound_link")
6084                ) {
6085                    var pixels = Object.keys(options.dynamicEvents.automatic_event_outbound_link);
6086
6087                    for(var i = 0;i<pixels.length;i++) {
6088                        var event = Utils.clone(options.dynamicEvents.automatic_event_outbound_link[pixels[i]]);
6089
6090                        if(pixels[i] !== "tiktok") { // TT doesn't support custom parameters
6091                            event.params["text"] = text;
6092                            if(target_url){
6093                                event.params["target_url"] = target_url;
6094                            }
6095                            Utils.copyProperties(Utils.getRequestParams(), event.params);
6096                        }
6097
6098
6099                        getPixelBySlag(pixels[i]).fireEvent(event.name, event);
6100                    }
6101                }
6102
6103
6104
6105
6106            });
6107
6108        }
6109
6110        // setup AdSense Event
6111        if (options.dynamicEvents.hasOwnProperty("automatic_event_adsense")) {
6112
6113            var isOverGoogleAd = false;
6114
6115            $(document)
6116                .on('mouseover', 'ins iframe', function () { //class adsbygoogle adsbygoogle-noablate ??
6117                    isOverGoogleAd = true;
6118                })
6119                .on('mouseout', 'iframe', function () {
6120                    isOverGoogleAd = false;
6121                });
6122
6123            $(window)
6124                .on( "blur",function () {
6125                    if (isOverGoogleAd) {
6126                        if(options.dynamicEvents.hasOwnProperty("automatic_event_adsense")) {
6127                            var pixels = Object.keys(options.dynamicEvents.automatic_event_adsense);
6128                            for (var i = 0; i < pixels.length; i++) {
6129                                var event = Utils.clone(options.dynamicEvents.automatic_event_adsense[pixels[i]]);
6130                                if ( pixels[i] !== 'tiktok') {
6131                                    Utils.copyProperties(Utils.getRequestParam
6131s(), event.params);
6132                                }
6133                                getPixelBySlag(pixels[i]).onAdSenseEvent(event);
6134                            }
6135                        }
6136
6137                        $.each(options.triggerEventTypes, function (triggerType, events) {
6138                            $.each(events, function (eventId, triggers) {
6139                                switch (triggerType) {
6140                                    case 'ad_sense_click':
6141                                        Utils.fireTriggerEvent(eventId);
6142                                        break;
6143                                }
6144                            });
6145                        });
6146                    }
6147                })
6148                .trigger("focus");
6149
6150        }
6151
6152        //setup adsense for custom events
6153        var dynamicAdsenseEventsTriggers = 0
6154        $.each(options.triggerEventTypes, function (triggerType, events) {
6155            if(triggerType == "ad_sense_click") {
6156                dynamicAdsenseEventsTriggers++;
6157            }
6158        });
6159        if (dynamicAdsenseEventsTriggers > 0) {
6160
6161            var isOverGoogleAd = false;
6162
6163            $(document)
6164                .on('mouseover', 'ins > ins > iframe', function () {
6165                    isOverGoogleAd = true;
6166                })
6167                .on('mouseout', 'iframe', function () {
6168                    isOverGoogleAd = false;
6169                });
6170
6171            $(window)
6172                .on( "blur",function () {
6173                    if (isOverGoogleAd) {
6174
6175                        $.each(options.triggerEventTypes, function (triggerType, events) {
6176                            $.each(events, function (eventId, triggers) {
6177                                switch (triggerType) {
6178                                    case 'ad_sense_click':
6179                                        Utils.fireTriggerEvent(eventId);
6180                                        break;
6181                                }
6182                            });
6183                        });
6184                    }
6185                })
6186                .trigger("focus");
6187
6188        }
6189
6190
6191        // page scroll event
6192        if (options.dynamicEvents.hasOwnProperty("automatic_event_scroll")
6193        ) {
6194
6195            var singlePageScroll = function () {
6196
6197
6198                var docHeight = $(document).height() - $(window).height();
6199                var isFired = false;
6200
6201                if (options.dynamicEvents.hasOwnProperty("automatic_event_scroll")) {
6202                    var pixels = Object.keys(options.dynamicEvents.automatic_event_scroll);
6203                    for(var i = 0;i<pixels.length;i++) {
6204                        var event = Utils.clone(options.dynamicEvents.automatic_event_scroll[pixels[i]]);
6205                        var scroll = Math.round(docHeight * event.scroll_percent / 100)// convert % to absolute positions
6206
6207                        if(scroll < $(window).scrollTop()) {
6208                            if ( pixels[i] !== 'tiktok') {
6209                                Utils.copyProperties(Utils.getRequestParam
6209s(), event.params);
6210                            }
6211                            getPixelBySlag(pixels[i]).onPageScroll(event);
6212                            isFired = true
6213                        }
6214                    }
6215                }
6216                if(isFired) {
6217                    $(document).off("scroll",singlePageScroll);
6218                }
6219            }
6220            $(document).on("scroll",singlePageScroll);
6221        }
6222
6223
6224        if (options.dynamicEvents.hasOwnProperty("automatic_event_time_on_page")) {
6225            var pixels = Object.keys(options.dynamicEvents.automatic_event_time_on_page);
6226            var time = options.dynamicEvents.automatic_event_time_on_page[pixels[0]].time_on_page; // the same for all pixel
6227            setTimeout(function(){
6228                for(var i = 0;i<pixels.length;i++) {
6229                    var event = Utils.clone(options.dynamicEvents.automatic_event_time_on_page[pixels[i]]);
6230                    if ( pixels[i] !== 'tiktok') {
6231                        Utils.copyProperties(Utils.getRequestParam
6231s(), event.params);
6232                    }
6233                    getPixelBySlag(pixels[i]).onTime(event);
6234                }
6235            },time*1000);
6236        }
6237
6238        // setup Dynamic events
6239
6240        $.each(options.triggerEventTypes, function (triggerType, events) {
6241
6242            $.each(events, function (eventId, triggers) {
6243                switch (triggerType) {
6244                    case 'url_click':
6245                        //@see: Utils.setupURLClickEvents()
6246                        break;
6247
6248                    case 'css_click':
6249                        Utils.setupCSSClickEvents(eventId, triggers);
6250                        break;
6251
6252                    case 'css_mouseover':
6253                        Utils.setupMouseOverClickEvents(eventId, triggers);
6254                        break;
6255
6256                    case 'scroll_pos':
6257                        Utils.setupScrollPosEvents(eventId, triggers);
6258                        break;
6259                    case 'comment':
6260                        Utils.setupCommentEvents(eventId, triggers);
6261                        break;
6262                    case 'video_view':
6263                        //@see: Utils.checkYouTubeCompletion() and Utils.addYouTubeEvents()
6264                        break;
6265
6266                    case 'form_field':
6267                        Utils.setupFormFieldEvents(eventId, triggers);
6268                        break;
6269                }
6270
6271            });
6272
6273            if ( triggerType == "email_link" ) {
6274                Utils.setupEmailLinkEvents( events )
6275            }
6276
6277        });
6278
6279        // setup WooCommerce events
6280        if (options.woo.enabled) {
6281
6282            // Woo CartFlow AddToCart
6283            if (options.dynamicEvents.hasOwnProperty("wcf_add_to_cart_on_next_step_click")) {
6284                $("body").on("click",'.wcf-next-step-link',function () {
6285                    var pixels = Object.keys(options.dynamicEvents.wcf_add_to_cart_on_next_step_click);
6286                    for(var i = 0;i<pixels.length;i++) {
6287                        var event = Utils.clone(options.dynamicEvents.wcf_add_to_cart_on_next_step_click[pixels[i]])
6288                        getPixelBySlag(pixels[i]).fireEvent(event.name, event);
6289                    }
6290                });
6291            }
6292            // Woo CartFlow Bump AddToCart
6293            if(options.dynamicEvents.hasOwnProperty("wcf_add_to_cart_on_bump_click") ||
6294                options.dynamicEvents.hasOwnProperty("wcf_bump")) {
6295                $("body").on('change','.wcf-bump-order-cb',function () {
6296
6297                    if(this.checked) {
6298                        if(options.dynamicEvents.hasOwnProperty("wcf_add_to_cart_on_bump_click")) {
6299                            var pixels = Object.keys(options.dynamicEvents.wcf_add_to_cart_on_bump_click);
6300                            for(var i = 0;i<pixels.length;i++) {
6301                                var event = Utils.clone(options.dynamicEvents.wcf_add_to_cart_on_bump_click[pixels[i]]);
6302                                getPixelBySlag(pixels[i]).fireEvent(event.name, event);
6303                            }
6304                        }
6305
6306
6307                        if(options.dynamicEvents.hasOwnProperty("wcf_bump")) {
6308                            var pixels = Object.keys(options.dynamicEvents.wcf_bump);
6309                            for(var i = 0;i<pixels.length;i++) {
6310                                var event = Utils.clone(options.dynamicEvents.wcf_bump[pixels[i]]);
6311                                getPixelBySlag(pixels[i]).fireEvent(event.name, event);
6312                            }
6313                        }
6314
6315                    } else {
6316                        if(options.dynamicEvents.hasOwnProperty("wcf_remove_from_cart_on_bump_click")) {
6317                            var pixels = Object.keys(options.dynamicEvents.wcf_remove_from_cart_on_bump_click);
6318                            for(var i = 0;i<pixels.length;i++) {
6319                                var event = Utils.clone(options.dynamicEvents.wcf_remove_from_cart_on_bump_click[pixels[i]]);
6320                                getPixelBySlag(pixels[i]).fireEvent(event.name, event);
6321                            }
6322                        }
6323
6324                    }
6325
6326
6327                });
6328            }
6329
6330
6331            // WooCommerce AddToCart
6332            if (options.dynamicEvents.hasOwnProperty("woo_add_to_cart_on_button_click")
6333                && options.woo.hasOwnProperty("addToCartCatchMethod")
6334                && options.woo.addToCartCatchMethod === "add_cart_js"
6335            ) {
6336                // Loop, any kind of "simple" product, except external
6337                $('.add_to_cart_button:not(.product_type_variable,.product_type_bundle,.single_add_to_cart_button)').on("click",function (e) {
6338
6339                    var $button = $(this);
6340                    var $prod_info = $button.siblings('.pys_list_name_productdata').data();
6341                    var product_id = $(this).data('product_id');
6342                    Cookies.set('productlist', JSON.stringify($prod_info), { expires: 1,path: '/' })
6343                    var product_id = $(this).data('product_id');
6344                    if (typeof product_id !== 'undefined') {
6345
6346                        if(options.dynamicEvents.hasOwnProperty("woo_add_to_cart_on_button_click")){
6347                            var tmpEventID = pys_generate_token();
6348                            $.each(options.dynamicEvents.woo_add_to_cart_on_button_click, function (i, tag) {
6349                                tag.eventID = tmpEventID;
6350                            });
6351                        }
6352
6353                        Facebook.onWooAddToCartOnButtonEvent(product_id,$(this));
6354                        Analytics.onWooAddToCartOnButtonEvent(product_id, $prod_info);
6355                        GTM.onWooAddToCartOnButtonEvent(product_id, $prod_info);
6356                        GAds.onWooAddToCartOnButtonEvent(product_id);
6357                        Pinterest.onWooAddToCartOnButtonEvent(product_id);
6358                        Bing.onWooAddToCartOnButtonEvent(product_id);
6359                        TikTok.onWooAddToCartOnButtonEvent(product_id);
6360                    }
6361
6362                });
6363
6364                // Single Product
6365                // tap try to https://stackoverflow.com/questions/30990967/on-tap-click-event-firing-twice-how-to-avoid-it
6366                //  $(document) not work
6367                $('body').onFirst('click','button.single_add_to_cart_button,.single_add_to_cart_button',function (e) {
6368
6369                    var $button = $(this);
6370                    var $prod_info = $button.siblings('.pys_list_name_productdata').data();
6371                    var product_id = $(this).data('product_id');
6372                    Cookies.set('productlist', JSON.stringify($prod_info), { expires: 1,path: '/' })
6373                    if ($button.hasClass('disabled')) {
6374                        return;
6375                    }
6376
6377                    var $form = $button.closest('form');
6378
6379                    var product_type = Utils.PRODUCT_SIMPLE;
6380                    var is_external = false;
6381
6382                    if ($form.length === 0) {
6383                        is_external = true;
6384                    } else if ($form.hasClass('variations_form')) {
6385                        product_type = Utils.PRODUCT_VARIABLE;
6386                    } else if($form.hasClass('bundle_form')) {
6387                        product_type = Utils.PRODUCT_BUNDLE;
6388                    } else if($form.hasClass('grouped_form')) {
6389                        product_type = Utils.PRODUCT_GROUPED;
6390                    }
6391
6392
6393
6394                    var product_id;
6395                    var qty;
6396                    if (product_type === Utils.PRODUCT_GROUPED) {
6397                        qty = 1;
6398                        product_id = parseInt($form.find('*[name="add-to-cart"]').val());
6399                    } else if (product_type === Utils.PRODUCT_VARIABLE) {
6400                        product_id = parseInt($form.find('*[name="add-to-cart"]').val());
6401                        var qtyTag = $form.find('input[name="quantity"]');
6402                        if(qtyTag.length <= 0) {
6403                            qtyTag = $form.find('select[name="quantity"]');
6404                        }
6405                        qty = parseInt(qtyTag.val());
6406                    } else if (is_external) {
6407                        product_id = options.woo.singleProductId;
6408                        qty = 1;
6409                    } else {
6410                        product_id = parseInt($form.find('*[name="add-to-cart"]').val());
6411                        var qtyTag = $form.find('input[name="quantity"]');
6412                        if(qtyTag.length <= 0) {
6413                            qtyTag = $form.find('select[name="quantity"]');
6414                        }
6415                        qty = parseInt(qtyTag.val());
6416                    }
6417
6418                    //
6419                    if(options.dynamicEvents.hasOwnProperty("woo_add_to_cart_on_button_click")){
6420                        var tmpEventID = pys_generate_token();
6421                        $.each(options.dynamicEvents.woo_add_to_cart_on_button_click, function (i, tag) {
6422                            tag.eventID = tmpEventID;
6423                        });
6424                    }
6425
6426                    Facebook.onWooAddToCartOnSingleEvent(product_id, qty, product_type, is_external, $form);
6427                    Analytics.onWooAddToCartOnSingleEvent(product_id, qty, product_type, is_external, $form, $prod_info);
6428                    GTM.onWooAddToCartOnSingleEvent(product_id, qty, product_type, is_external, $form, $prod_info);
6429                    GAds.onWooAddToCartOnSingleEvent(product_id, qty, product_type, is_external, $form);
6430                    Pinterest.onWooAddToCartOnSingleEvent(product_id, qty, product_type, is_external, $form);
6431                    Bing.onWooAddToCartOnSingleEvent(product_id, qty, product_type, is_external, $form);
6432                    TikTok.onWooAddToCartOnSingleEvent(product_id, qty, product_type, is_external, $form);
6433                });
6434
6435            } else {
6436                $('.add_to_cart_button:not(.product_type_variable,.product_type_bundle,.single_add_to_cart_button)').on("click",function (e) {
6437                    var $button = $(this);
6438                    var $prod_info = $button.siblings('.pys_list_name_productdata').data();
6439                    var product_id = $(this).data('product_id');
6440                    Cookies.set('productlist', JSON.stringify($prod_info), { expires: 1,path: '/' })
6441                });
6442
6443                // Single Product
6444                // tap try to https://stackoverflow.com/questions/30990967/on-tap-click-event-firing-twice-how-to-avoid-it
6445                //  $(document) not work
6446                $('body').onFirst('click','button.single_add_to_cart_button,.single_add_to_cart_button',function (e) {
6447
6448                    var $button = $(this);
6449                    var $prod_info = $button.siblings('.pys_list_name_productdata').data();
6450                    Cookies.set('productlist', $prod_info, { expires: 1,path: '/' })
6451                });
6452            }
6453
6454            // WooCommerce Affiliate
6455            if (options.dynamicEvents.hasOwnProperty("woo_affiliate")) {
6456
6457                // Loop, external
6458                $('.product_type_external').on("click",function (e) {
6459
6460                    var product_id = $(this).data('product_id');
6461
6462                    if (typeof product_id !== 'undefined') {
6463                        Facebook.onWooAffiliateEvent(product_id);
6464                        Analytics.onWooAffiliateEvent(product_id);
6465                        GTM.onWooAffiliateEvent(product_id);
6466                        GAds.onWooAffiliateEvent(product_id);
6467                        Pinterest.onWooAffiliateEvent(product_id);
6468                        Bing.onWooAffiliateEvent(product_id);
6469                    }
6470
6471                });
6472
6473            }
6474
6475            // WooCommerce RemoveFromCart
6476            if (options.dynamicEvents.hasOwnProperty("woo_remove_from_cart")) {
6477
6478                $('body').on('click', options.woo.removeFromCartSelector, function (e) {
6479
6480                    var $a = $(e.currentTarget),
6481                        href = $a.attr('href');
6482
6483                    // extract cart item hash from remove button URL
6484                    var regex = new RegExp("[\\?&]remove_item=([^&#]*)"),
6485                        results = regex.exec(href);
6486
6487                    if (results !== null) {
6488
6489                        var item_hash = results[1];
6490
6491                        if (options.dynamicEvents["woo_remove_from_cart"].hasOwnProperty(item_hash)) {
6492                            var events = options.dynamicEvents["woo_remove_from_cart"][item_hash];
6493                            Utils.fireEventForAllPixel("onWooRemoveFromCartEvent",events)
6494                        }
6495
6496                    }
6497
6498                });
6499
6500            }
6501
6502            // WooCommerce PayPal
6503            if (options.dynamicEvents.hasOwnProperty("woo_paypal")) {
6504
6505                // Non-default binding used to avoid situations when some code in external js
6506                // stopping events propagation, eg. returns false, and our handler will never called
6507                $(document).onFirst('submit click', '#place_order', function (e) {
6508
6509                    var method = $('form[name="checkout"] input[name="payment_method"]:checked').val();
6510
6511                    if (method !== 'paypal') {
6512                        return;
6513                    }
6514                    var events = options.dynamicEvents.woo_paypal;
6515                    Utils.fireEventForAllPixel("onWooPayPalEvent",events)
6516
6517                });
6518
6519            }
6520
6521            // WooCommerce checkout progress
6522            if(options.dynamicEvents.hasOwnProperty("woo_initiate_checkout_progress_f") ) {
6523
6524                $(document).on("change",".woocommerce-validated #billing_first_name",function () {
6525                    var pixels = Object.keys(options.dynamicEvents.woo_initiate_checkout_progress_f);
6526                    for (var i = 0; i < pixels.length; i++) {
6527                        var event = Utils.clone(options.dynamicEvents.woo_initiate_checkout_progress_f[pixels[i]]);
6528                        getPixelBySlag(pixels[i]).onWooCheckoutProgressStep(event);
6529                    }
6530                });
6531            }
6532            if(options.dynamicEvents.hasOwnProperty("woo_initiate_checkout_progress_l")) {
6533
6534                $(document).on("change",".woocommerce-validated #billing_last_name",function () {
6535                    var pixels = Object.keys(options.dynamicEvents.woo_initiate_checkout_progress_l);
6536                    for (var i = 0; i < pixels.length; i++) {
6537                        var event = Utils.clone(options.dynamicEvents.woo_initiate_checkout_progress_l[pixels[i]]);
6538                        getPixelBySlag(pixels[i]).onWooCheckoutProgressStep(event);
6539                    }
6540                });
6541            }
6542
6543            if(options.dynamicEvents.hasOwnProperty("woo_initiate_checkout_progress_e")) {
6544
6545                $(document).on("change",".woocommerce-validated #billing_email",function () {
6546                    var pixels = Object.keys(options.dynamicEvents.woo_initiate_checkout_progress_e);
6547                    for (var i = 0; i < pixels.length; i++) {
6548                        var event = Utils.clone(options.dynamicEvents.woo_initiate_checkout_progress_e[pixels[i]]);
6549                        getPixelBySlag(pixels[i]).onWooCheckoutProgressStep(event);
6550                    }
6551                });
6552            }
6553            if(options.dynamicEvents.hasOwnProperty("woo_initiate_checkout_progress_o")) {
6554                $(document).onFirst('submit click', '#place_order', function () {
6555                    var shippingMethodFull = $('[name="shipping_method[0]"]:checked').val();
6556                    var shippingMethod = shippingMethodFull ? shippingMethodFull.split(':')[0] : '';
6557                    var pixels = Object.keys(options.dynamicEvents.woo_initiate_checkout_progress_o);
6558                    for (var i = 0; i < pixels.length; i++) {
6559                        var event = Utils.clone(options.dynamicEvents.woo_initiate_checkout_progress_o[pixels[i]]);
6560  
6560                      // Add shipping_method to event params
6561                        event.params = event.params || {};
6562                        event.params.checkout_option = shippingMethod;
6563                        getPixelBySlag(pixels[i]).onWooCheckoutProgressStep(event);
6564                    }
6565                });
6566            }
6567
6568
6569            // WooCommerce
6570
6571            $('.product.type-product a.woocommerce-loop-product__link').onFirst('click', function (evt) {
6572                var productId = $(this).closest('.product').find(".add_to_cart_button").attr("data-product_id");
6573                var eventTypes = ["woo_select_content_search", "woo_select_content_shop", "woo_select_content_tag", "woo_select_content_single", "woo_select_content_category"];
6574                var isEventFired = false;
6575
6576                for (var i = 0; i < eventTypes.length; i++) {
6577                    var eventType = eventTypes[i];
6578                    if (options.dynamicEvents.hasOwnProperty(eventType) && options.dynamicEvents[eventType].hasOwnProperty(productId)) {
6579                        if(Analytics.isEnabled()){
6580                            Analytics.onWooSelectContent(options.dynamicEvents[eventType][productId][Analytics.tag()]);
6581                        }
6582                        if(GTM.isEnabled()){
6583                            GTM.onWooSelectContent(options.dynamicEvents[eventType][productId][GTM.tag()]);
6584                        }
6585                        isEventFired = true;
6586                        break;
6587                    }
6588                }
6589
6590                if (!isEventFired) {
6591                    let prod_info = $(this).parent().find('.pys_list_name_productdata').data();
6592                    if (prod_info) {
6593                        const select_prod_list = {};
6594                        if (prod_info['pys_list_name_productlist_name']) {
6595                            select_prod_list.list_name = prod_info['pys_list_name_productlist_name']
6596                        }
6597                        if (prod_info['pys_list_name_productlist_id']) {
6598                            select_prod_list.list_id = prod_info['pys_list_name_productlist_id']
6599                        }
6600                        const url = new URL(window.location.href);
6601                        select_prod_list.url = url.origin + url.pathname;
6602                        Cookies.set('select_prod_list', JSON.stringify(select_prod_list), { expires: 1,path: '/' });
6603                    }
6604                }
6605            });
6606
6607        }
6608
6609        // setup EDD events
6610        if (options.edd.enabled) {
6611
6612            // EDD AddToCart
6613            if (options.dynamicEvents.hasOwnProperty("edd_add_to_cart_on_button_click")) {
6614
6615                $('form.edd_download_purchase_form .edd-add-to-cart').on("click",function (e) {
6616
6617                    var $button = $(this);
6618                    var $form = $button.closest('form');
6619                    var variable_price = $button.data('variablePrice'); // yes/no
6620                    var price_mode = $button.data('priceMode'); // single/multi
6621                    var ids = [];
6622                    var quantities = [];
6623                    var qty;
6624                    var id;
6625
6626                    if (variable_price === 'yes' && price_mode === 'multi') {
6627
6628                        id = $form.find('input[name="download_id"]').val();
6629
6630                        // get selected variants
6631                        $.each($form.find('input[name="edd_options[price_id][]"]:checked'), function (i, el) {
6632                            ids.push(id + '_' + $(el).val());
6633                        });
6634
6635                        // get qty for selected variants
6636                        $.each(ids, function (i, variant_id) {
6637
6638                            var variant_index = variant_id.split('_', 2);
6639                            qty = $form.find('input[name="edd_download_quantity_' + variant_index[1] + '"]').val();
6640
6641                            if (typeof qty !== 'undefined') {
6642                                quantities.push(qty);
6643                            } else {
6644                                quantities.push(1);
6645                            }
6646
6647                        });
6648
6649                    } else if (variable_price === 'yes' && price_mode === 'single') {
6650
6651                        id = $form.find('input[name="download_id"]').val();
6652                        ids.push(id + '_' + $form.find('input[name="edd_options[price_id][]"]:checked').val());
6653
6654                        qty = $form.find('input[name="edd_download_quantity"]').val();
6655
6656                        if (typeof qty !== 'undefined') {
6657                            quantities.push(qty);
6658                        } else {
6659                            quantities.push(1);
6660                        }
6661
6662                    } else {
6663
6664                        ids.push($button.data('downloadId'));
6665
6666                        qty = $form.find('input[name="edd_download_quantity"]').val();
6667
6668                        if (typeof qty !== 'undefined') {
6669                            quantities.push(qty);
6670                        } else {
6671                            quantities.push(1);
6672                        }
6673                    }
6674
6675                    // fire event for each download/variant
6676                    $.each(ids, function (i, download_id) {
6677
6678                        var q = parseInt(quantities[i]);
6679                        var variant_index = download_id.toString().split('_', 2);
6680                        var price_index;
6681
6682                        if (variant_index.length === 2) {
6683                            download_id = variant_index[0];
6684                            price_index = variant_index[1];
6685                        }
6686
6687                        Facebook.onEddAddToCartOnButtonEvent(download_id, price_index, q);
6688                        Analytics.onEddAddToCartOnButtonEvent(download_id, price_index, q);
6689                        GTM.onEddAddToCartOnButtonEvent(download_id, price_index, q);
6690                        GAds.onEddAddToCartOnButtonEvent(download_id, price_index, q);
6691                        Pinterest.onEddAddToCartOnButtonEvent(download_id, price_index, q);
6692                        Bing.onEddAddToCartOnButtonEvent(download_id, price_index, q);
6693                        TikTok.onEddAddToCartOnButtonEvent(download_id, price_index, q);
6694
6695                    });
6696
6697                });
6698
6699            }
6700
6701            // EDD RemoveFromCart
6702            if (options.dynamicEvents.hasOwnProperty("edd_remove_from_cart") ) {
6703
6704                $('form#edd_checkout_cart_form .edd_cart_remove_item_btn').on("click",function (e) {
6705
6706                    var href = $(this).attr('href');
6707                    var key = href.substring(href.indexOf('=') + 1).charAt(0);
6708
6709                    if (options.dynamicEvents.edd_remove_from_cart.hasOwnProperty(key)) {
6710                        var events = options.dynamicEvents.edd_remove_from_cart[key];
6711                        Utils.fireEventForAllPixel("onEddRemoveFromCartEvent",events)
6712                    }
6713
6714                });
6715
6716            }
6717
6718        }
6719
6720        Utils.setupURLClickEvents();
6721
6722        // setup Comment Event
6723        if (options.dynamicEvents.hasOwnProperty("automatic_event_comment")
6724        ) {
6725
6726            $('form.comment-form').on("submit",function () {
6727                if (options.dynamicEvents.hasOwnProperty("automatic_event_comment")) {
6728                    var pixels = Object.keys(options.dynamicEvents.automatic_event_comment);
6729                    for (var i = 0; i < pixels.length; i++) {
6730                        var event = Utils.clone(options.dynamicEvents.automatic_event_comment[pixels[i]]);
6731                        if ( pixels[i] !== 'tiktok') {
6732                            Utils.copyProperties(Utils.getRequestParam
6732s(), event.params);
6733                        }
6734                        getPixelBySlag(pixels[i]).onCommentEvent(event);
6735                    }
6736                }
6737            });
6738
6739        }
6740
6741        // setup Form Event
6742        if ( options.dynamicEvents.hasOwnProperty("automatic_event_form")) {
6743
6744            $(document).onFirst('submit', 'form', function (e) {
6745
6746                var $form = $(this);
6747
6748                // exclude WP forms
6749                if ($form.hasClass('comment-form') || $form.hasClass('search-form') || $form.attr('id') === 'adminbarsearch') {
6750                    return;
6751                }
6752
6753                // exclude Woo forms
6754                if ($form.hasClass('woocommerce-product-search') || $form.hasClass('cart') || $form.hasClass('woocommerce-cart-form') ||
6755                    $form.hasClass('woocommerce-shipping-calculator') || $form.hasClass('checkout') || $form.hasClass('checkout_coupon')) {
6756                    return;
6757                }
6758
6759                // exclude EDD forms
6760                if ($form.hasClass('edd_form') || $form.hasClass('edd_download_purchase_form')) {
6761                    return;
6762                }
6763                // exclude CF7 forms
6764                if ($form.hasClass('wpcf7-form')) {
6765                    return;
6766                }
6767                // exclude Gravity forms
6768                if ($form.attr('id') && $form.attr('id').includes('gform')) {
6769                    var target = $form.attr('target');
6770                    if (target && target.indexOf('gform_ajax_frame') !== -1) {
6771                        return;
6772                    }
6773                }
6774                // exclude Forminator forms
6775                if ($form.hasClass('forminator-custom-form') || $form.hasClass('forminator_ajax')) {
6776                    return;
6777                }
6778                // exclude WPforms forms
6779                if ($form.hasClass('wpforms-form') || $form.hasClass('wpforms-ajax-form')) {
6780                    return;
6781                }
6782                // exclude Formidable forms
6783                /*if ($form.hasClass('frm-show-form')) {
6784                    return;
6785                }*/
6786                // exclude Ninja Forms forms
6787                if ($form.parent().hasClass('nf-form-layout')) {
6788                    return;
6789                }
6790                // exclude Fluent forms
6791                if ($form.hasClass('frm-fluent-form')) {
6792                    return;
6793                }
6794
6795                // exclude WS form forms
6796                if ($form.hasClass('wsf-form') ) {
6797                    return;
6798                }
6799
6800                // exclude WS form forms
6801                if ( $form.hasClass( 'elementor-form' ) ) {
6802                    return;
6803                }
6804
6805                if(!options.enable_success_send_form) {
6806                    var params = {
6807                        form_id: $form.attr('id'),
6808                        form_class: $form.attr('class') ? $form.attr('class') : $form.attr('id'),
6809                        text: $form.find('[type="submit"]').is('input') ?
6810                            $form.find('[type="submit"]').val() : $form.find('[type="submit"]').text()
6811                    };
6812
6813                    if (options.dynamicEvents.hasOwnProperty("automatic_event_form")) {
6814                        var pixels = Object.keys(options.dynamicEvents.automatic_event_form);
6815                        for (var i = 0; i < pixels.length; i++) {
6816                            var event = Utils.clone(options.dynamicEvents.automatic_event_form[pixels[i]]);
6817
6818                            if (pixels[i] === "tiktok") {
6819                                getPixelBySlag(pixels[i]).fireEvent(event.name, event);
6820                            } else {
6821                                Utils.copyProperties(params, event.params,)
6822                                Utils.copyProperties(Utils.getRequestParam
6822s(), event.params);
6823                                getPixelBySlag(pixels[i]).onFormEvent(event);
6824                            }
6825                        }
6826                    }
6827                }
6828            });
6829
6830
6831        }
6832
6833        jQuery(document).on('elementor/popup/show', function(event) {
6834            for (var i = 0; i < jQuery(".wpcf7-form").length; i++) {
6835                wpcf7.init(jQuery(".wpcf7-form")[i]);
6836            }
6837        });
6838
6839        document.addEventListener( 'wpcf7mailsent', function ( event ) {
6840            let form_id = event.detail.contactFormId,
6841                sendEventId = null,
6842                disabled_form_action = false;
6843            if ( options.triggerEventTypes.hasOwnProperty( 'CF7' ) ) {
6844                $.each( options.triggerEventTypes.CF7, function ( eventId, triggers ) {
6845                    $.each( triggers, function ( index, trigger ) {
6846                        $.each( trigger.forms, function ( i, value ) {
6847                            if ( value == form_id ) {
6848                                sendEventId = eventId;
6849                                disabled_form_action = trigger.disabled_form_action;
6850                            }
6851                        } )
6852                    } );
6853                } );
6854            }
6855            if ( sendEventId != null ) {
6856                Utils.fireTriggerEvent( sendEventId );
6857            }
6858            sendFormAction( $( event.target ), form_id, sendEventId, disabled_form_action );
6859
6860        }, false );
6861
6862        //GravityForm
6863        jQuery( document ).on( 'gform_confirmation_loaded', function ( event, formId ) {
6864            let form_id = formId,
6865                sendEventId = null,
6866                disabled_form_action = false;
6867            if ( options.triggerEventTypes.hasOwnProperty( 'gravity' ) ) {
6868                $.each( options.triggerEventTypes.gravity, function ( eventId, triggers ) {
6869                    $.each( triggers, function ( index, trigger ) {
6870                        $.each( trigger.forms, function ( i, value ) {
6871                            if ( value == form_id ) {
6872                                disabled_form_action = trigger.disabled_form_action;
6873                                sendEventId = eventId;
6874                            }
6875                        } )
6876                    } );
6877                } );
6878            }
6879
6880            if ( sendEventId != null ) {
6881                Utils.fireTriggerEvent( sendEventId );
6882            }
6883            sendFormAction( $( event.target ), form_id, sendEventId, disabled_form_action );
6884            jQuery( document ).off( 'gform_confirmation_loaded' );
6885        } );
6886        //Forminator
6887        $( document ).on( 'forminator:form:submit:success', function ( event ) {
6888
6889            let form_id = $( event.target ).find( 'input[name="form_id"]' ).val(),
6890                sendEventId = null,
6891                disabled_form_action = false;
6892            if ( options.triggerEventTypes.hasOwnProperty( 'forminator' ) ) {
6893                $.each( options.triggerEventTypes.forminator, function ( eventId, triggers ) {
6894                    $.each( triggers, function ( index, trigger ) {
6895                        $.each( trigger.forms, function ( i, value ) {
6896                            if ( value == form_id ) {
6897                                disabled_form_action = trigger.disabled_form_action;
6898                                sendEventId = eventId;
6899                            }
6900                        } )
6901                    } );
6902                } );
6903            }
6904            if ( sendEventId != null ) {
6905                Utils.fireTriggerEvent( sendEventId );
6906            }
6907            sendFormAction( $( event.target ), form_id, sendEventId, disabled_form_action );
6908        } );
6909
6910        //WPForm
6911        $( 'form.wpforms-form' ).on( 'wpformsAjaxSubmitSuccess', ( event ) => {
6912
6913            let form_id = $( event.target ).attr( 'data-formid' ),
6914                sendEventId = null,
6915                disabled_form_action = false;
6916
6917            if ( options.triggerEventTypes.hasOwnProperty( 'wpforms' ) ) {
6918                $.each( options.triggerEventTypes.wpforms, function ( eventId, triggers ) {
6919                    $.each( triggers, function ( index, trigger ) {
6920                        $.each( trigger.forms, function ( i, value ) {
6921                            if ( value == form_id ) {
6922                                sendEventId = eventId;
6923                                disabled_form_action = trigger.disabled_form_action;
6924                            }
6925                        } )
6926                    } );
6927                } );
6928            }
6929            if ( sendEventId != null ) {
6930                Utils.fireTriggerEvent( sendEventId );
6931            }
6932            sendFormAction( $( event.target ), form_id, sendEventId, disabled_form_action );
6933        } )
6934
6935        $( document ).on( 'frmFormComplete', function ( event, form, response ) {
6936            const form_id = $( form ).find( 'input[name="form_id"]' ).val();
6937            let sendEventId = null,
6938                disabled_form_action = false;
6939            if ( options.triggerEventTypes.hasOwnProperty( 'formidable' ) ) {
6940                $.each( options.triggerEventTypes.formidable, function ( eventId, triggers ) {
6941                    $.each( triggers, function ( index, trigger ) {
6942                        $.each( trigger.forms, function ( i, value ) {
6943                            if ( value == form_id ) {
6944                                disabled_form_action = trigger.disabled_form_action;
6945                                sendEventId = eventId;
6946                            }
6947                        } )
6948                    } );
6949                } );
6950            }
6951            if ( sendEventId != null ) {
6952                Utils.fireTriggerEvent( sendEventId );
6953            }
6954            sendFormAction( $( event.target ), form_id, sendEventId, disabled_form_action );
6955
6956        } );
6957
6958        // Ninja Forms
6959        $( document ).onFirst( 'nfFormSubmitResponse', function ( event, data ) {
6960            const form_id = data.response.data.form_id;
6961            let sendEventId = null,
6962                disabled_form_action = false;
6963            if ( options.triggerEventTypes.hasOwnProperty( 'ninjaform' ) ) {
6964                $.each( options.triggerEventTypes.ninjaform, function ( eventId, triggers ) {
6965                    $.each( triggers, function ( index, trigger ) {
6966                        $.each( trigger.forms, function ( i, value ) {
6967                            if ( value == form_id ) {
6968                                disabled_form_action = trigger.disabled_form_action;
6969                                sendEventId = eventId;
6970                            }
6971                        } )
6972                    } );
6973                } );
6974            }
6975            if ( sendEventId != null ) {
6976                Utils.fireTriggerEvent( sendEventId );
6977            }
6978            sendFormAction( $( event.target ), form_id, sendEventId, disabled_form_action );
6979        } );
6980
6981
6982        $(document).on('fluentform_submission_success', function ( event, data ) {
6983            let $form = data.form; // Submitted form
6984            let config = data.config; // Form configuration
6985            let response = data.response; // Server response
6986
6987
6988            let $formItem = $form;
6989            let form_id = config.id;
6990            let sendEventId = null,
6991                disabled_form_action = false;
6992            if ( options.triggerEventTypes.hasOwnProperty( 'fluentform' ) ) {
6993                $.each( options.triggerEventTypes.fluentform, function ( eventId, triggers ) {
6994                    $.each( triggers, function ( index, trigger ) {
6995                        $.each( trigger.forms, function ( i, value ) {
6996                            if ( value == form_id ) {
6997                                disabled_form_action = trigger.disabled_form_action;
6998                                sendEventId = eventId;
6999                            }
7000                        } )
7001                    } );
7002                } );
7003            }
7004
7005            if ( sendEventId != null ) {
7006                Utils.fireTriggerEvent( sendEventId );
7007            }
7008            sendFormAction( $( event.target ), form_id, sendEventId, disabled_form_action );
7009        } );
7010
7011        //WSForm
7012        $( document ).on( 'wsf-submit-complete', ( event, form_object, form_id ) => {
7013            let sendEventId = null,
7014                disabled_form_action = false;
7015            if ( options.triggerEventTypes.hasOwnProperty( 'wsform' ) ) {
7016                $.each( options.triggerEventTypes.wsform, function ( eventId, triggers ) {
7017                    $.each( triggers, function ( index, trigger ) {
7018                        $.each( trigger.forms, function ( i, value ) {
7019                            if ( value == form_id ) {
7020                                disabled_form_action = trigger.disabled_form_action;
7021                                sendEventId = eventId;
7022                            }
7023                        } )
7024                    } );
7025                } );
7026            }
7027
7028            if ( sendEventId != null ) {
7029                Utils.fireTriggerEvent( sendEventId );
7030            }
7031            sendFormAction( $( event.target ), form_id, sendEventId, disabled_form_action );
7032        } )
7033
7034        // Elementor Forms
7035        let forms = document.querySelectorAll( '.elementor-form' );
7036        // Apply the observer to each form
7037        forms.forEach( function ( form ) {
7038            observeElementorForm( form );
7039        } );
7040
7041        // watching Elementor Popup forms
7042        let observer = new MutationObserver( function ( mutationsList, observer ) {
7043            for ( let i = 0; i < mutationsList.length; i++ ) {
7044                let popupForm = document.querySelector( '[class*="elementor-popup"] form' );
7045                if ( popupForm ) {
7046                    observeElementorForm( popupForm );
7047                    observer.disconnect();
7048                    break;
7049                }
7050            }
7051        } );
7052        observer.observe( document.body, { childList: true, subtree: true } );
7053
7054        // load pixel APIs
7055        Utils.loadPixels();
7056
7057        // setup Enrich content
7058        if(Utils.isCheckoutPage()) {
7059            Utils.addCheckoutFields();
7060        }
7061        if(options.woo.hasOwnProperty('woo_view_content_variation_is_selected') && options.woo.woo_view_content_variation_is_selected) {
7062            handleWooViewContentVariation()
7063        }
7064
7065    });
7066
7067
7068    function handleWooViewContentVariation() {
7069        var form = $('form.variations_form');
7070
7071        form.on('change', 'select', function() {
7072            var selectedAttributes = {};
7073            form.find('select').each(function() {
7074                var attributeName = $(this).data('attribute_name') || $(this).attr('name');
7075                var attributeValue = $(this).val();
7076                if (attributeValue) {
7077                    selectedAttributes[attributeName] = attributeValue;
7078                }
7079            });
7080
7081            $.ajax({
7082                url: options.ajaxUrl,
7083                type: 'POST',
7084                data: {
7085                    action: 'get_variation_info',
7086                    product_id: form.data('product_id'), // Передаем ID основного товара
7087                    attributes: selectedAttributes
7088                },
7089                success: function(response) {
7090                    if (response.success) {
7091                        $.each(response.data, function(slug) {
7092                            $.each(response.data[slug], function(index, event) {
7093                                getPixelBySlag(slug).fireEvent(event.name, event);
7094                            });
7095                        });
7096                    } else {
7097                        console.log('Error retrieving data:', response.data);
7098                    }
7099                }
7100            });
7101        });
7102    }
7103    var sendFormAction = function (form_target, formId, customEventId = null, disabled = false){
7104        var params = {
7105            form_id: formId,
7106            text: form_target.find('[type="submit"]').is('input') ? form_target.find('[type="submit"]').val() :
7107                form_target.find('.forminator-button-submit').text() != '' ? form_target.find('.forminator-button-submit').text() :
7108                    form_target.find('[type="submit"]').text()
7109        };
7110
7111        if (options.dynamicEvents.hasOwnProperty("automatic_event_form")) {
7112            var pixels = Object.keys(options.dynamicEvents.automatic_event_form);
7113            for (var i = 0; i < pixels.length; i++) {
7114
7115                if ( disabled && customEventId && typeof options.triggerEvents[customEventId][pixels[i]] !== 'undefined') {
7116                    continue;
7117                }
7118                var event = options.dynamicEvents.automatic_event_form[pixels[i]];
7119                if (pixels[i] === "tiktok") {
7120                    getPixelBySlag(pixels[i]).fireEvent(event.name, event);
7121                } else {
7122                    Utils.copyProperties(params, event.params)
7123                    Utils.copyProperties(Utils.getRequestParams(), event.params);
7124                    getPixelBySlag(pixels[i]).onFormEvent(event);
7125                }
7126            }
7127        }
7128    }
7129
7130    var setupEmailLinks = function ( disabled_for_pixels = [] ) {
7131        if ( options.dynamicEvents.hasOwnProperty( "automatic_event_email_link" ) ) {
7132            var pixels = Object.keys( options.dynamicEvents.automatic_event_email_link );
7133            for ( var i = 0; i < pixels.length; i++ ) {
7134                if ( disabled_for_pixels.indexOf(pixels[ i ]) === -1 ) {
7135                    var event = Utils.clone( options.dynamicEvents.automatic_event_email_link[ pixels[ i ] ] );
7136                    if ( pixels[ i ] !== 'tiktok' ) {
7137                        Utils.copyProperties( Utils.getRequestParams(), event.params );
7138                    }
7139                    getPixelBySlag( pixels[ i ] ).fireEvent( event.name, event );
7140                }
7141            }
7142        }
7143    }
7144
7145    //Elementor Forms Observer
7146    var observeElementorForm = function ( form ) {
7147        let observer = new MutationObserver( function ( mutations ) {
7148
7149            for ( let i = 0; i < mutations.length; i++ ) {
7150                let mutation = mutations[ i ];
7151
7152                if ( mutation.type === 'childList' || mutation.type === 'attributes' ) {
7153                    if ( $( form ).find( '.elementor-message-success' ).length > 0 ) {
7154
7155                        let form_id = $( form ).attr( 'id' );
7156                        if ( !form_id ) {
7157                            form_id = $( form ).find( 'input[name="form_id"]' ).val();
7158                        }
7159
7160                        let sendEventId = null,
7161                            disabled_form_action = false;
7162                        if ( options.triggerEventTypes.hasOwnProperty( 'elementor_form' ) ) {
7163                            $.each( options.triggerEventTypes.elementor_form, function ( eventId, triggers ) {
7164                                $.each( triggers, function ( index, trigger ) {
7165                                    $.each( trigger.forms, function ( i, value ) {
7166                                        if ( value == form_id ) {
7167                                            disabled_form_action = trigger.disabled_form_action;
7168                                            sendEventId = eventId;
7169                                        }
7170                                    })
7171                                } );
7172                            } );
7173                        }
7174                        if ( sendEventId != null ) {
7175                            Utils.fireTriggerEvent( sendEventId );
7176                        }
7177                        sendFormAction( $( event.target ), form_id, sendEventId, disabled_form_action );
7178
7179                        observer.disconnect();
7180                        break;
7181                    }
7182                }
7183            }
7184        } );
7185
7186        // Start observing the form for changes
7187        observer.observe( form, {
7188            attributes: true,
7189            childList: true,
7190            subtree: true
7191        } );
7192    }
7193
7194}(jQuery, pysOptions);
7195
7196
7197function pys_generate_token() {
7198    return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
7199        (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
7200    );
7201}
7202function getBundlePriceOnSingleProduct(data) {
7203    var items_sum = 0;
7204    jQuery(".bundle_form .bundled_product").each(function(index){
7205        var id = jQuery(this).find(".cart").data("bundled_item_id");
7206        var item_price = data.prices[id];
7207        var item_quantity = jQuery(this).find(".bundled_qty").val();
7208        if(!jQuery(this).hasClass("bundled_item_optional") ||
7209            jQuery(this).find(".bundled_product_optional_checkbox input").prop('checked')) {
7210            items_sum += item_price*item_quantity;
7211        }
7212    });
7213    return items_sum;
7214}
7215function getUrlParameter(sParam) {
7216    var sPageURL = window.location.search.substring(1),
7217        sURLVariables = sPageURL.split('&'),
7218        sParameterName,
7219        i;
7220
7221    for (i = 0; i < sURLVariables.length; i++) {
7222        sParameterName = sURLVariables[i].split('=');
7223
7224        if (sParameterName[0] === sParam) {
7225            return sParameterName[1] === undefined ? true : decodeURIComponent(sParameterName[1]);
7226        }
7227    }
7228    return false;
7229};
7230function inArray(needle, haystack) {
7231    var length = haystack.length;
7232    for(var i = 0; i < length; i++) {
7233        if(haystack[i] == needle) return true;
7234    }
7235    return false;
7236}
7237
7238function getCookieYes(key) {
7239    const cookiesObj = document.cookie
7240        .split(";")
7241        .reduce((ac, cv) => {
7242            const [k, v] = cv.split("=");
7243            if (k && v) ac[k.trim()] = v;
7244            return ac;
7245        }, {});
7246    const consentCookie = cookiesObj["cookieyes-consent"] || cookiesObj["wt_consent"];
7247    if (!consentCookie) return undefined;
7248    const { [key]: value } = consentCookie
7249        .split(",")
7250        .reduce((obj, pair) => {
7251            const [k, v] = pair.split(":");
7252            if (k && v) obj[k] = v;
7253            return obj;
7254        }, {});
7255    return value;
7256}
7257
7258function getRootDomain(useSubdomain = false) {
7259    const hostname = window.location.hostname; // Get the current hostname
7260    // Check if tldjs is defined before using it
7261    if (typeof tldjs === "undefined") {
7262        console.warn("tldjs is not defined");
7263        return hostname; // Return hostname as a fallback
7264    }
7265
7266    const rootDomain = tldjs.getDomain(hostname); // Use tldjs to extract the root domain
7267
7268    // Return the root domain with or without a leading dot based on useSubdomain
7269    return rootDomain ? (useSubdomain ? '.' + rootDomain : rootDomain) : hostname;
7270}

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.