PageSourceSearch

https://cigkoftem.com/wp-content/plugins/pixelyoursite/dist/scripts/public.js?ver=11.2.0.2

js cigkoftem.com collected 2026-10-08 08:18:33 UTC 160,454 bytes, 3,815 lines download raw bytes

1/* global pysOptions */
2
3
4! function ($, options) {
5    if (options.debug) {
6        console.log('PYS:', options);
7    }
8    var uniqueId = {};
9
10    let gtm_variables = {};
11    let gtm_datalayername = "dynamicVariable";
12
13    var domain = '';
14    if(options.hasOwnProperty("track_cookie_for_subdomains") && options.track_cookie_for_subdomains) {
15        domain = getRootDomain(true);
16    }
17    /**
18     * Resolve parameter value based on mode (static or dynamic)
19     *
20     * @param {Object|string} param - Parameter object with { value, selector } or string value
21     * @returns {string|null} - Resolved value
22     */
23    function resolveParamValue(param) {
24        // Handle old format (string)
25        if (typeof param === 'string') {
26            return param;
27        }
28        if (typeof param === 'object' && param !== null) {
29            return param.value || param;
30        }
31
32        return null;
33    }
34    var dummyPinterest = function () {
35
36        /**
37         * Public API
38         */
39        return {
40            isEnabled: function () {},
41            disable: function () {},
42            loadPixel: function () {},
43            fireEvent: function (name, data) {
44                return false;
45            },
46            onCommentEvent: function () {},
47            onDownloadEvent: function (params) {},
48            onFormEvent: function (params) {},
49            onWooAddToCartOnButtonEvent: function (product_id) {},
50            onWooAddToCartOnSingleEvent: function (product_id, qty, is_variable, is_external, $form) {},
51            onWooRemoveFromCartEvent: function (cart_item_hash) {},
52            onEddAddToCartOnButtonEvent: function (download_id, price_index, qty) {},
53            onEddRemoveFromCartEvent: function (item) {},
54            onPageScroll: function (event) {},
55            onTime: function (event) {},
56
57        }
58
59    }();
60
61    var dummyBing = function () {
62
63        /**
64         * Public API
65         */
66        return {
67            isEnabled: function () {},
68            disable: function () {},
69            loadPixel: function () {},
70            fireEvent: function (name, data) {
71                return false;
72            },
73            onAdSenseEvent: function () {},
74            onClickEvent: function (params) {},
75            onWatchVideo: function (params) {},
76            onCommentEvent: function () {},
77            onFormEvent: function (params) {},
78            onDownloadEvent: function (params) {},
79            onWooAddToCartOnButtonEvent: function (product_id) {},
80            onWooAddToCartOnSingleEvent: function (product_id, qty, is_variable, is_external, $form) {},
81            onWooRemoveFromCartEvent: function (cart_item_hash) {},
82            onWooAffiliateEvent: function (product_id) {},
83            onWooPayPalEvent: function () {},
84            onEddAddToCartOnButtonEvent: function (download_id, price_index, qty) {},
85            onEddRemoveFromCartEvent: function (item) {},
86            onPageScroll: function (event) {},
87            onTime: function (event) {},
88        }
89
90    }();
91
92	var dummyReddit = function () {
93		/**
94		 * Public API
95		 */
96		return {
97			tag: function () {
98				return "reddit";
99			},
100			isEnabled: function () {},
101			disable: function () {},
102			loadPixel: function () {},
103			fireEvent: function ( name, data ) {
104				return false;
105			},
106			onAdSenseEvent: function ( event ) {},
107			onClickEvent: function ( params ) {},
108			onWatchVideo: function ( params ) {},
109			onCommentEvent: function ( event ) {},
110			onFormEvent: function ( params ) {},
111			onDownloadEvent: function ( params ) {},
112			onWooAddToCartOnButtonEvent: function ( product_id ) {},
113			onWooAddToCartOnSingleEvent: function ( product_id, qty, product_type, is_external, $form ) {},
114			onWooRemoveFromCartEvent: function ( cart_item_hash ) {},
115			onWooAffiliateEvent: function ( product_id ) {},
116			onWooPayPalEvent: function ( event ) {},
117			onEddAddToCartOnButtonEvent: function ( download_id, price_index, qty ) {},
118			onEddRemoveFromCartEvent: function ( item ) {},
119			onPageScroll: function ( event ) {},
120			onTime: function ( event ) {},
121		}
122	}();
123
124
125	var Utils = function (options) {
126
127        var Pinterest = dummyPinterest;
128
129        var Bing = dummyBing;
130
131		var Reddit = dummyReddit;
132
133        var gtag_loaded = false;
134
135        var gtm_loaded = false;
136
137        let isNewSession = checkSession();
138
139        var utmTerms = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content'];
140
141        var utmId = ['fbadid', 'gadid', 'padid', 'bingid'];
142
143        let dataLayerName = 'dataLayerPYS';
144
145        let GTMdataLayerName = 'dataLayer';
146
147        function validateEmail(email) {
148            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,}))$/;
149            return re.test(email);
150        }
151        function getDomain(url) {
152
153            url = url.replace(/(https?:\/\/)?(www.)?/i, '');
154
155            if (url.indexOf('/') !== -1) {
156                return url.split('/')[0];
157            }
158
159            return url;
160        }
161        function loadPixels() {
162
163            if (!options.gdpr.all_disabled_by_api) {
164
165                if (!options.gdpr.facebook_disabled_by_api) {
166                    Facebook.loadPixel();
167                }
168
169                if (!options.gdpr.analytics_disabled_by_api) {
170                    Analytics.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	            if (!options.gdpr.reddit_disabled_by_api) {
186		            Reddit.loadPixel();
187	            }
188            }
189            if (options.gdpr.consent_magic_integration_enabled && typeof CS_Data !== "undefined") {
190                if (typeof CS_Data.cs_google_analytics_consent_mode !== "undefined" && CS_Data.cs_google_analytics_consent_mode == 1) {
191                    Analytics.loadPixel();
192                }
193            }
194
195        }
196
197        function checkSession() {
198            if( Cookies.get('pys_start_session') === undefined ||
199                Cookies.get('pys_session_limit') === undefined) {
200                firstVisit = true;
201                return true
202            }
203            return false
204
205        }
206
207        function getTrafficSource() {
208
209            try {
210
211                let referrer = document.referrer.toString(),
212                    source;
213
214                let direct = referrer.length === 0;
215                let internal = direct ? false : referrer.indexOf(options.siteUrl) === 0;
216                let external = !direct && !internal;
217
218                if (external === false) {
219                    source = 'direct';
220                } else {
221                    source = referrer;
222                }
223
224                if (source !== 'direct') {
225                    // leave only domain (Issue #70)
226                    return getDomain(source);
227                } else {
228                    return source;
229                }
230
231            } catch (e) {
232                console.error(e);
233                return 'direct';
234            }
235
236        }
237
238        /**
239         * Return query variables object with where property name is query variable
240         * and property value is query variable value.
241         */
242        function getQueryVars() {
243
244            try {
245
246                var result = {},
247                    tmp = [];
248
249                window.location.search
250                    .substr(1)
251                    .split("&")
252                    .forEach(function (item) {
253
254                        tmp = item.split('=');
255
256                        if (tmp.length > 1) {
257                            result[tmp[0]] = tmp[1];
258                        }
259
260                    });
261
262                return result;
263
264            } catch (e) {
265                console.error(e);
266                return {};
267            }
268
269        }
270
271
272        function getLandingPageValue() {
273            let name = "pys_landing_page"
274            if(options.visit_data_model === "last_visit") {
275                name = "last_pys_landing_page"
276            }
277            if(Cookies.get(name) && Cookies.get(name) !== "undefined") {
278                return Cookies.get(name);
279            }
280            else if(options.hasOwnProperty("tracking_analytics") && options.tracking_analytics.TrafficLanding){
281                return options.tracking_analytics.TrafficLanding;
282            } else{
283                return "";
284            }
285        }
286        function getTrafficSourceValue() {
287            let name = "pysTrafficSource"
288            if(options.visit_data_model === "last_visit") {
289                name = "last_pysTrafficSource"
290            }
291            if(Cookies.get(name) && Cookies.get(name) !== "undefined") {
292                return Cookies.get(name);
293            }
294            else if(options.hasOwnProperty("tracking_analytics") && options.tracking_analytics.TrafficSource){
295                return options.tracking_analytics.TrafficSource;
296            } else{
297                return "";
298            }
299        }
300
301        function getUTMId(useLast = false) {
302            try {
303                let cookiePrefix = 'pys_'
304                let terms = [];
305                if (useLast) {
306                    cookiePrefix = 'last_pys_'
307                }
308                $.each(utmId, function (index, name) {
309                    if (Cookies.get(cookiePrefix + name)) {
310                        terms[name] = Cookies.get(cookiePrefix + name)
311                    }
312                    else if(options.hasOwnProperty("tracking_analytics") && options.tracking_analytics.TrafficUtmsId[name]) {
313                        terms[name] = filterEmails(options.tracking_analytics.TrafficUtmsId[name])
314                    }
315                });
316                return terms;
317            } catch (e) {
318                console.error(e);
319                return [];
320            }
321        }
322        /**
323         * Return UTM terms from request query variables or from cookies.
324         */
325        function getUTMs(useLast = false) {
326
327            try {
328                let cookiePrefix = 'pys_'
329                if(useLast) {
330                    cookiePrefix = 'last_pys_'
331                }
332                let terms = [];
333                $.each(utmTerms, function (index, name) {
334                    if (Cookies.get(cookiePrefix + name)) {
335                        let value = Cookies.get(cookiePrefix + name);
336                        terms[name] = filterEmails(value); // do not allow email in request params (Issue #70)
337                    }
338                    else if(options.hasOwnProperty("tracking_analytics") && options.tracking_analytics.TrafficUtms[name]) {
339                        terms[name] = filterEmails(options.tracking_analytics.TrafficUtms[name])
340                    }
341                });
342
343                return terms;
344
345            } catch (e) {
346                console.error(e);
347                return [];
348            }
349
350        }
351
352        function getDateTime() {
353            var dateTime = new Array();
354            var date = new Date(),
355                days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
356                months = ['January', 'February', 'March', 'April', 'May', 'June',
357                    'July', 'August', 'September', 'October', 'November', 'December'
358                ],
359                hours = ['00-01', '01-02', '02-03', '03-04', '04-05', '05-06', '06-07', '07-08',
360                    '08-09', '09-10', '10-11', '11-12', '12-13', '13-14', '14-15', '15-16', '16-17',
361                    '17-18', '18-19', '19-20', '20-21', '21-22', '22-23', '23-24'
362                ];
363            dateTime.push(hours[date.getHours()]);
364            dateTime.push(days[date.getDay()]);
365            dateTime.push(months[date.getMonth()]);
366            return dateTime;
367        }
368
369        function filterEmails(value) {
370            return validateEmail(value) ? undefined : value;
371        }
372
373        /**
374         * PUBLIC API
375         */
376        return {
377            PRODUCT_SIMPLE : 0,
378            PRODUCT_VARIABLE : 1,
379            PRODUCT_BUNDLE : 2,
380            PRODUCT_GROUPED : 3,
381            utmTerms : utmTerms,
382            utmId : utmId,
383            fireEventForAllPixel:function(functionName,events){
384                if (events.hasOwnProperty(Facebook.tag()))
385                    Facebook[functionName](events[Facebook.tag()]);
386                if (events.hasOwnProperty(Analytics.tag()))
387                    Analytics[functionName](events[Analytics.tag()]);
388                if (events.hasOwnProperty(Pinterest.tag()))
389                    Pinterest[functionName](events[Pinterest.tag()]);
390                if (events.hasOwnProperty(Bing.tag()))
391                    Bing[functionName](events[Bing.tag()]);
392	            if (events.hasOwnProperty(Reddit.tag()))
393		            Reddit[functionName](events[Reddit.tag()]);
394
395                if (events.hasOwnProperty(GTM.tag()))
396                    GTM[functionName](events[GTM.tag()]);
397            },
398
399            setupPinterestObject: function () {
400                Pinterest = window.pys.Pinterest || Pinterest;
401                return Pinterest;
402            },
403
404            setupBingObject: function () {
405                Bing = window.pys.Bing || Bing;
406                return Bing;
407            },
408
409	        setupRedditObject: function () {
410		        Reddit = window.pys.Reddit || Reddit;
411		        return Reddit;
412	        },
413
414            // Clone all object members to another and return it
415            copyProperties: function (from, to) {
416                for (var key in from) {
417                    if("function" == typeof from[key]) {
418                        continue;
419                    }
420                    to[key] = from[key];
421                }
422                return to;
423            },
424
425            manageCookies: function () {
426
427                if (options.gdpr.cookiebot_integration_enabled && typeof Cookiebot !== 'undefined') {
428                    if (Cookiebot.consented === false && !Cookiebot.consent['marketing'] && !Cookiebot.consent['statistics']) {
429                        return;
430                    }
431                }
432                let cm_consent_not_expressed = false;
433                if ( options.gdpr.consent_magic_integration_enabled && window.CS_Data !== undefined && window.CS_Data.cs_refresh_after_consent == 1 ) {
434                    if ( Cookies.get( 'cs_viewed_cookie_policy' ) === undefined ) {
435                        cm_consent_not_expressed = true;
436                    }
437                }
438
439                if( !cm_consent_not_expressed && isNewSession && !options.cookie.disabled_all_cookie && !options.cookie.disabled_start_session_cookie) {
440                    let duration = options.last_visit_duration * 60000
441                    var now = new Date();
442                    now.setTime(now.getTime() + duration);
443                    Cookies.set('pys_session_limit', true,{ expires: now, path: '/',domain: domain })
444                    Cookies.set('pys_start_session', true,{path: '/',domain: domain});
445                }
446
447                if (options.ajaxForServerEvent && !Cookies.get('pbid') && Facebook.isEnabled()) {
448                    jQuery.ajax({
449                        url: options.ajaxUrl,
450                        dataType: 'json',
451                        data: {
452                            action: 'pys_get_pbid'
453                        },
454                        success: function (res) {
455                            if (res.data && res.data.pbid != false && options.send_external_id) {
456                                if(!(options.cookie.disabled_all_cookie || options.cookie.externalID_disabled_by_api)){
457                                    var expires = parseInt(options.external_id_expire || 180);
458                                    Cookies.set('pbid', res.data.pbid, { expires: expires, path: '/',domain: domain });
459                                }
460
461                                if(options.hasOwnProperty('facebook')) {
462                                    options.facebook.advancedMatching = {
463                                        ...options.facebook.advancedMatching,  // spread current advancedMatching values
464                                        external_id: res.data.pbid
465                                    };
466                                }
467                            }
468                        }
469                    });
470                } else if (Cookies.get('pbid') && Facebook.isEnabled()){
471                    if(Facebook.advancedMatching() && Facebook.advancedMatching().external_id && !(options.cookie.disabled_all_cookie || options.cookie.externalID_disabled_by_api)){
472                        let expires = parseInt(options.external_id_expire || 180);
473                        Cookies.set('pbid', Facebook.advancedMatching().external_id, { expires: expires, path: '/',domain: domain });
474                    }
475                }
476
477                let expires = parseInt(options.cookie_duration); //  days
478                let queryVars = getQueryVars();
479                let landing = window.location.href.split('?')[0];
480                try {
481                    // save data for first visit
482                    if(Cookies.get('pys_first_visit') === undefined && (!options.cookie.disabled_all_cookie)) {
483
484                        if(!options.cookie.disabled_first_visit_cookie)
485                        {
486                            Cookies.set('pys_first_visit', true, { expires: expires, path: '/',domain: domain });
487                        }
488                        else {
489                            Cookies.remove('pys_first_visit')
490                        }
491
492                        if(!options.cookie.disabled_trafficsource_cookie)
493                        {
494                            Cookies.set('pysTrafficSource', getTrafficSource(), { expires: expires,path: '/',domain: domain });
495                        }
496                        else {
497                            Cookies.remove('pysTrafficSource')
498                        }
499
500                        if(!options.cookie.disabled_landing_page_cookie)
501                        {
502                            Cookies.set('pys_landing_page',landing,{ expires: expires,path: '/',domain: domain });
503                        }
504                        else {
505                            Cookies.remove('pys_landing_page')
506                        }
507
508                        if(!options.cookie.disabled_utmTerms_cookie)
509                        {
510                            $.each(utmTerms, function (index, name) {
511                                if (queryVars.hasOwnProperty(name)) {
512                                    Cookies.set('pys_' + name, queryVars[name], { expires: expires,path: '/',domain: domain });
513                                } else {
514                                    Cookies.remove('pys_' + name)
515                                }
516                            });
517                        }
518                        else {
519                            $.each(utmTerms, function (index, name) {
520                                Cookies.remove('pys_' + name)
521                            });
522                        }
523
524                        if(!options.cookie.disabled_utmId_cookie)
525                        {
526                            $.each(utmId,function(index,name) {
527                                if (queryVars.hasOwnProperty(name)) {
528                                    Cookies.set('pys_' + name, queryVars[name], { expires: expires,path: '/',domain: domain });
529                                } else {
530                                    Cookies.remove('pys_' + name)
531                                }
532                            })
533                        }
534                        else {
535                            $.each(utmId, function (index, name) {
536                                Cookies.remove('pys_' + name)
537                            });
538                        }
539                    }
540
541                    // save data for last visit if it new session
542                    if(isNewSession && (!options.cookie.disabled_all_cookie)) {
543                        if(!options.cookie.disabled_trafficsource_cookie)
544                        {
545                            Cookies.set('last_pysTrafficSource', getTrafficSource(), { expires: expires,path: '/',domain: domain });
546                        }
547                        else {
548                            Cookies.remove('last_pysTrafficSource')
549                        }
550
551                        if(!options.cookie.disabled_landing_page_cookie)
552                        {
553                            Cookies.set('last_pys_landing_page',landing,{ expires: expires,path: '/',domain: domain });
554                        }
555                        else {
556                            Cookies.remove('last_pys_landing_page')
557                        }
558
559                        if(!options.cookie.disabled_utmTerms_cookie)
560                        {
561                            $.each(utmTerms, function (index, name) {
562                                if (queryVars.hasOwnProperty(name)) {
563                                    Cookies.set('last_pys_' + name, queryVars[name], { expires: expires,path: '/',domain: domain });
564                                } else {
565                                    Cookies.remove('last_pys_' + name)
566                                }
567                            });
568                        }
569                        else {
570                            $.each(utmTerms, function (index, name) {
571                                Cookies.remove('last_pys_' + name)
572                            });
573                        }
574
575                        if(!options.cookie.disabled_utmId_cookie)
576                        {
577                            $.each(utmId,function(index,name) {
578                                if (queryVars.hasOwnProperty(name)) {
579                                    Cookies.set('last_pys_' + name, queryVars[name], { expires: expires,path: '/',domain: domain });
580                                } else {
581                                    Cookies.remove('last_pys_' + name)
582                                }
583                            })
584                        }
585                        else {
586                            $.each(utmId, function (index, name) {
587                                Cookies.remove('last_pys_' + name)
588                            });
589                        }
590
591                    }
592                    if(options.cookie.disabled_start_session_cookie) {
593                        Cookies.remove('pys_start_session')
594                        Cookies.remove('pys_session_limit')
595                    }
596                    if(options.cookie.disabled_all_cookie)
597                    {
598                        Cookies.remove('pys_first_visit')
599                        Cookies.remove('pysTrafficSource')
600                        Cookies.remove('pys_landing_page')
601                        Cookies.remove('last_pys_landing_page')
602                        Cookies.remove('last_pysTrafficSource')
603                        Cookies.remove('pys_start_session')
604                        Cookies.remove('pys_session_limit')
605                        $.each(Utils.utmTerms, function (index, name) {
606                            Cookies.remove('pys_' + name)
607                        });
608                        $.each(Utils.utmId,function(index,name) {
609                            Cookies.remove('pys_' + name)
610                        })
611                        $.each(Utils.utmTerms, function (index, name) {
612                            Cookies.remove('last_pys_' + name)
613                        });
614                        $.each(Utils.utmId,function(index,name) {
615                            Cookies.remove('last_pys_' + name)
616                        });
617                    }
618                } catch (e) {
619                    console.error(e);
620                }
621            },
622            /**
623             * Generate unique ID
624             */
625            generateUniqueId : function (event) {
626                if(event.eventID.length == 0 || (event.type == "static" && options.ajaxForServerStaticEvent) || (event.type !== "static" && options.ajaxForServerEvent)) {
627                    let idKey = event.hasOwnProperty('custom_event_post_id') ? event.custom_event_post_id : event.e_id;
628                    if (!uniqueId.hasOwnProperty(idKey)) {
629                        uniqueId[idKey] = pys_generate_token();
630                    }
631                    return uniqueId[idKey];
632                }
633                else if(event.eventID.length !== 0)
634                {
635                    return event.eventID;
636                }
637            },
638
639            // Flatten object for sendBeacon compatibility
640            flattenObject: function (obj, prefix = '', res = {}) {
641                for (const [key, value] of Object.entries(obj)) {
642                    const prefixedKey = prefix
643                        ? (Array.isArray(obj) ? `${prefix}[${key}]` : `${prefix}[${key}]`)
644                        : key;
645                    if (value !== null && typeof value === 'object' && !(value instanceof File)) {
646                        this.flattenObject(value, prefixedKey, res);
647                    } else {
648                        res[prefixedKey] = value;
649                    }
650                }
651                return res;
652            },
653
654            sendServerAjaxRequest : function(url, data) {
655                if (data.action === 'pys_api_event' && data.pixel === 'facebook' && window.pysFacebookRest) {
656                    // Use Facebook REST API
657                    this.sendRestAPIRequest(data, 'facebook');
658                    return;
659                }
660
661                // Check if sendBeacon is enabled and supported
662                if (options.useSendBeacon && navigator.sendBeacon) {
663                    try {
664                        // Flatten the data object for sendBeacon compatibility
665                        const flattenedData = this.flattenObject(data);
666                        const formData = new URLSearchParams();
667
668                        // Convert flattened data to URLSearchParams
669                        for (const [key, value] of Object.entries(flattenedData)) {
670                            if (value !== null && value !== undefined) {
671                                formData.append(key, value);
672                            }
673                        }
674
675                        // Try to send using sendBeacon
676                        const success = navigator.sendBeacon(url, formData);
677                        if (success) {
678                            return; // Successfully sent via sendBeacon
679                        }
680                    } catch (e) {
681                        // If sendBeacon fails, fall back to jQuery.ajax
682                        if (options.debug) {
683                            console.log('PYS: sendBeacon failed, falling back to jQuery.ajax:', e);
684                        }
685                    }
686                }
687
688                // Fallback to jQuery.ajax
689                jQuery.ajax( {
690                    type: 'POST',
691                    url: url,
692                    data: data,
693                    headers: {
694                        'Cache-Control': 'no-cache'
695                    },
696                    success: function () {
697                    },
698                } );
699            },
700
701            sendRestAPIRequest: function (data, platform) {
702                let restApiUrl;
703
704                // Get platform-specific REST API configuration
705                switch (platform) {
706                    case 'facebook':
707                        restApiUrl = window.pysFacebookRest ? window.pysFacebookRest.restApiUrl : '/wp-json/pys-facebook/v1/event';
708                        break;
709                    default:
710                        console.error('PYS: Unknown platform for REST API:', platform);
711                        this.sendAjaxFallback(data);
712                        return;
713                }
714
715                // Prepare data for REST API
716                const restApiData = {
717                    event: data.event,
718                    data: JSON.stringify(data.data || {}),
719                    ids: JSON.stringify(data.ids || []),
720                    eventID: data.event_id || data.eventID || '',
721                    woo_order: data.woo_order || '0',
722                    edd_order: data.edd_order || '0'
723                };
724
725                // Try to send using sendBeacon first (if enabled)
726                if (options.useSendBeacon && navigator.sendBeacon) {
727                    try {
728                        const formData = new URLSearchParams();
729                        for (const [key, value] of Object.entries(restApiData)) {
730                            formData.append(key, value);
731                        }
732
733                        if (navigator.sendBeacon(restApiUrl, formData)) {
734                            return;
735                        }
736                    } catch (e) {
737                        // sendBeacon failed, continue to fetch
738                    }
739                }
740
741                // Try to send using fetch with REST API
742                if (window.fetch) {
743                    const headers = {
744                        'Content-Type': 'application/json'
745                    };
746
747                    fetch(restApiUrl, {
748                        method: 'POST',
749                        headers: headers,
750                        body: JSON.stringify(restApiData)
751                    })
752                        .then(response => {
753                            if (!response.ok) {
754                                throw new Error(platform + ' REST API request failed: ' + response.status);
755                            }
756                        })
757                        .catch(error => {
758                            // Fallback to AJAX if REST API fails
759                            if (options.debug) {
760                                console.log('PYS: ' + platform + ' REST API failed, falling back to AJAX:', error);
761                            }
762                            this.sendAjaxFallback(data);
763                        });
764                } else {
765                    // Fallback to AJAX if fetch is not supported
766                    this.sendAjaxFallback(data);
767                }
768            },
769
770
771
772            // Fallback AJAX method
773            sendAjaxFallback: function (data) {
774                jQuery.ajax({
775                    type: 'POST',
776                    url: options.ajaxUrl,
777                    data: data,
778                    headers: {
779                        'Cache-Control': 'no-cache'
780                    },
781                    success: function () {
782                    },
783                });
784            },
785            // clone object
786            clone: function(obj) {
787                var copy;
788
789                // Handle the 3 simple types, and null or undefined
790                if (null == obj || "object" != typeof obj) return obj;
791
792                // Handle Date
793                if (obj instanceof Date) {
794                    copy = new Date();
795                    copy.setTime(obj.getTime());
796                    return copy;
797                }
798
799                // Handle Array
800                if (obj instanceof Array) {
801                    copy = [];
802                    for (var i = 0, len = obj.length; i < len; i++) {
803                        if("function" == typeof obj[i]) {
804                            continue;
805                        }
806                        copy[i] = Utils.clone(obj[i]);
807                    }
808                    return copy;
809                }
810
811                // Handle Object
812                if (obj instanceof Object) {
813                    copy = {};
814                    for (var attr in obj) {
815                        if (obj.hasOwnProperty(attr)) {
816                            if("function" == typeof obj[attr]) {
817                                continue;
818                            }
819                            copy[attr] = Utils.clone(obj[attr]);
820                        }
821                    }
822                    return copy;
823                }
824
825                return obj;
826            },
827
828            // Returns array of elements with given tag name
829            getTagsAsArray: function (tag) {
830                return [].slice.call(document.getElementsByTagName(tag));
831            },
832
833            getRequestParams: function () {
834                return [];
835            },
836
837            /**
838             * CUSTOM EVENTS
839             */
840
841            setupMouseOverClickEvents: function (eventId, triggers) {
842
843                // Non-default binding used to avoid situations when some code in external js
844                // stopping events propagation, eg. returns false, and our handler will never called
845                document.addEventListener('mouseover', function(event) {
846                    var matchedElements = Array.from(document.querySelectorAll(triggers));
847                    var clickedElement = event.target;
848                    var closestMatch = clickedElement.closest(triggers);
849                    if (matchedElements.includes(clickedElement) || closestMatch){
850                        if (event.target.classList.contains('pys-mouse-over-' + eventId)) {
851                            return true;
852                        } else {
853                            event.target.classList.add('pys-mouse-over-' + eventId);
854                        }
855
856                        Utils.fireTriggerEvent(eventId);
857                    }
858                });
859
860            },
861
862            setupCSSClickEvents: function (eventId, triggers) {
863                // Non-default binding used to avoid situations when some code in external js
864                // stopping events propagation, eg. returns false, and our handler will never called
865                document.addEventListener('click', function(event) {
866                    let matchedElements = Array.from(document.querySelectorAll(triggers)),
867                        clickedElement = event.target,
868                        closestMatch = clickedElement.closest(triggers);
869
870                    if (matchedElements.includes(clickedElement) || closestMatch){
871                        Utils.fireTriggerEvent(eventId);
872                    }
873                }, true);
874            },
875
876            setupURLClickEvents: function () {
877
878                if( !options.triggerEventTypes.hasOwnProperty('url_click') ) {
879                    return;
880                }
881                // Non-default binding used to avoid situations when some code in external js
882                // stopping events propagation, eg. returns false, and our handler will never called
883                $('a[data-pys-event-id]').onFirst('click', function (evt) {
884
885                    $(this).attr('data-pys-event-id').split(',').forEach(function (eventId) {
886
887                        eventId = parseInt(eventId);
888
889                        if (isNaN(eventId) === false) {
890                            Utils.fireTriggerEvent(eventId);
891                        }
892
893                    });
894
895                });
896
897
898            },
899
900            setupScrollPosEvents: function (eventId, triggers) {
901
902                var scrollPosThresholds = {},
903                    docHeight = $(document).height() - $(window).height();
904
905                // convert % to absolute positions
906                $.each(triggers, function (index, scrollPos) {
907
908                    // convert % to pixels
909                    scrollPos = docHeight * scrollPos / 100;
910                    scrollPos = Math.round(scrollPos);
911
912                    scrollPosThresholds[scrollPos] = eventId;
913
914                });
915
916                $(document).on("scroll",function () {
917
918                    var scrollPos = $(window).scrollTop();
919
920                    $.each(scrollPosThresholds, function (threshold, eventId) {
921
922                        // position has not reached yes
923                        if (scrollPos <= threshold) {
924                            return true;
925                        }
926
927                        // fire event only once
928                        if (eventId === null) {
929                            return true;
930                        } else {
931                            scrollPosThresholds[threshold] = null;
932                        }
933
934                        Utils.fireTriggerEvent(eventId);
935
936                    });
937
938                });
939
940
941            },
942            setupCommentEvents : function (eventId,triggers) {
943                $('form.comment-form').on("submit",function () {
944                    Utils.fireTriggerEvent(eventId);
945                });
946            },
947
948            /**
949             * Events
950             */
951
952            fireTriggerEvent: function (eventId) {
953
954                if (!options.triggerEvents.hasOwnProperty(eventId)) {
955                    return;
956                }
957
958                var event = {};
959                var events = options.triggerEvents[eventId];
960
961                if (events.hasOwnProperty('facebook')) {
962                    event = Utils.getFormFilledData(events.facebook);
963                    Facebook.fireEvent(event.name, event);
964                }
965
966                if (events.hasOwnProperty('ga')) {
967                    event = Utils.getFormFilledData(events.ga);
968                    Analytics.fireEvent(event.name, event);
969                }
970
971                if (events.hasOwnProperty('pinterest')) {
972                    event = Utils.getFormFilledData(events.pinterest);
973                    Pinterest.fireEvent(event.name, event);
974                }
975
976                if (events.hasOwnProperty('bing')) {
977                    event = Utils.getFormFilledData(events.bing);
978                    Bing.fireEvent(event.name, event);
979                }
980
981	            if (events.hasOwnProperty('reddit')) {
982                    event = Utils.getFormFilledData(events.reddit);
983                    Reddit.fireEvent(event.name, event);
984	            }
985
986                if (events.hasOwnProperty('gtm')) {
987                    event = Utils.getFormFilledData(events.gtm);
988                    GTM.fireEvent(event.name, event);
989                }
990            },
991
992            fireStaticEvents: function (pixel) {
993
994                if (options.staticEvents.hasOwnProperty(pixel)) {
995
996                    $.each(options.staticEvents[pixel], function (eventName, events) {
997                        $.each(events, function (index, eventData) {
998
999                            eventData.fired = eventData.fired || false;
1000
1001                            if (!eventData.fired) {
1002                                eventData = Utils.getFormFilledData(eventData);
1003                                var fired = false;
1004
1005                                // fire event
1006                                if ('facebook' === pixel) {
1007                                    fired = Facebook.fireEvent(eventData.name, eventData);
1008                                } else if ('ga' === pixel) {
1009                                    fired = Analytics.fireEvent(eventData.name, eventData);
1010                                } else if ('pinterest' === pixel) {
1011                                    fired = Pinterest.fireEvent(eventData.name, eventData);
1012                                } else if ('bing' === pixel) {
1013                                    fired = Bing.fireEvent(eventData.name, eventData);
1014                                } else if ('gtm' === pixel) {
1015                                    fired = GTM.fireEvent(eventData.name, eventData);
1016                                } else if ('reddit' === pixel) {
1017	                                fired = Reddit.fireEvent(eventData.name, eventData);
1018                                }
1019
1020                                // prevent event double event firing
1021                                eventData.fired = fired;
1022
1023                            }
1024
1025                        });
1026                    });
1027
1028                }
1029
1030            },
1031
1032            /**
1033             * Load tag's JS
1034             *
1035             * @link: https://developers.google.com/analytics/devguides/collection/gtagjs/
1036             * @link: https://developers.google.com/analytics/devguides/collection/gtagjs/custom-dims-mets
1037             */
1038            loadGoogleTag: function (id) {
1039
1040                if (!gtag_loaded) {
1041                    let dataLayerName = this.dataLayerName;
1042                    if(options.hasOwnProperty('GATags')){
1043                        switch (options.GATags.ga_datalayer_type) {
1044                            case 'default':
1045                                dataLayerName = 'dataLayerPYS';
1046                                break;
1047                            case 'custom':
1048                                dataLayerName = options.GATags.ga_datalayer_name;
1049                                break;
1050                            default:
1051                                dataLayerName = 'dataLayer';
1052                        }
1053                    }
1054                    this.dataLayerName = dataLayerName;
1055                    (function (window, document, src) {
1056                        var a = document.createElement('script'),
1057                            m = document.getElementsByTagName('script')[0];
1058                        a.async = 1;
1059                        a.src = src;
1060                        m.parentNode.insertBefore(a, m);
1061                    })(window, document, '//www.googletagmanager.com/gtag/js?id=' + id+'&l='+this.dataLayerName);
1062
1063                    window[dataLayerName] = window[dataLayerName] || [];
1064                    window.gtag = window.gtag || function gtag() {
1065                        window[dataLayerName].push(arguments);
1066                    };
1067
1068                    if ( options.google_consent_mode ) {
1069                        let data = {};
1070                        data[ 'analytics_storage' ] = options.gdpr.analytics_storage.enabled ? options.gdpr.analytics_storage.value : 'granted';
1071                        data[ 'ad_storage' ] = options.gdpr.ad_storage.enabled ? options.gdpr.ad_storage.value : 'granted';
1072                        data[ 'ad_user_data' ] = options.gdpr.ad_user_data.enabled ? options.gdpr.ad_user_data.value : 'granted';
1073                        data[ 'ad_personalization' ] = options.gdpr.ad_personalization.enabled ? options.gdpr.ad_personalization.value : 'granted';
1074
1075                        this.loadDefaultConsent( 'consent', 'default', data );
1076                    }
1077
1078                    gtag('js', new Date());
1079                    gtag_loaded = true;
1080
1081                }
1082
1083            },
1084
1085            loadDefaultConsent: function() {
1086                window[ this.dataLayerName ].push( arguments );
1087            },
1088
1089            loadGTMScript: function (id = '') {
1090                const domain = options.gtm.gtm_container_domain ?? 'www.googletagmanager.com';
1091                const loader = options.gtm.gtm_container_identifier ?? 'gtm';
1092                const gtm_auth = options.gtm.gtm_auth ?? ''; // Set this if needed
1093                const gtm_preview = options.gtm.gtm_preview ?? ''; // Set this if needed
1094                const datalayer_name = options.gtm.gtm_dataLayer_name ?? 'dataLayer';
1095
1096                window[ datalayer_name ] = window[ datalayer_name ] || [];
1097                window.gtag = window.gtag || function gtag() {
1098                    window[ datalayer_name ].push( arguments );
1099                };
1100
1101                if ( options.google_consent_mode ) {
1102                    let data = {};
1103                    data[ 'analytics_storage' ] = options.gdpr.analytics_storage.enabled ? options.gdpr.analytics_storage.value : 'granted';
1104                    data[ 'ad_storage' ] = options.gdpr.ad_storage.enabled ? options.gdpr.ad_storage.value : 'granted';
1105                    data[ 'ad_user_data' ] = options.gdpr.ad_user_data.enabled ? options.gdpr.ad_user_data.value : 'granted';
1106                    data[ 'ad_personalization' ] = options.gdpr.ad_personalization.enabled ? options.gdpr.ad_personalization.value : 'granted';
1107
1108                    this.GTMdataLayerName = datalayer_name;
1109                    this.loadDefaultGTMConsent( 'consent', 'default', data );
1110                }
1111
1112                (function(w, d, s, l, i) {
1113                    w[l] = w[l] || [];
1114                    w[l].push({ 'gtm.start': new Date().getTime(), event: 'gtm.js' });
1115                    const f = d.getElementsByTagName(s)[0];
1116                    const j = d.createElement(s);
1117                    const dl = l !== 'dataLayer' ? '&l=' + l : '';
1118                    j.async = true;
1119                    j.src = 'https://' + domain + '/' + loader + '.js?id=' + i + dl;
1120                    if (gtm_auth && gtm_preview) {
1121                        j.src += '&gtm_auth=' + gtm_auth + '&gtm_preview=' + gtm_preview + '&gtm_cookies_win=x';
1122                    }
1123                    f.parentNode.insertBefore(j, f);
1124                })(window, document, 'script', datalayer_name, id);
1125
1126            },
1127
1128            loadDefaultGTMConsent: function() {
1129                window[ this.GTMdataLayerName ].push( arguments );
1130            },
1131
1132            /**
1133             * GDPR
1134             */
1135
1136            loadPixels: function () {
1137
1138                if (options.gdpr.ajax_enabled && !options.gdpr.consent_magic_integration_enabled) {
1139
1140                    // retrieves actual PYS GDPR filters values which allow to avoid cache issues
1141                    $.get({
1142                        url: options.ajaxUrl,
1143                        dataType: 'json',
1144                        data: {
1145                            action: 'pys_get_gdpr_filters_values'
1146                        },
1147                        success: function (res) {
1148
1149                            if (res.success) {
1150
1151                                options.gdpr.all_disabled_by_api = res.data.all_disabled_by_api;
1152                                options.gdpr.facebook_disabled_by_api = res.data.facebook_disabled_by_api;
1153                                options.gdpr.analytics_disabled_by_api = res.data.analytics_disabled_by_api;
1154                                options.gdpr.google_ads_disabled_by_api = res.data.google_ads_disabled_by_api;
1155                                options.gdpr.pinterest_disabled_by_api = res.data.pinterest_disabled_by_api;
1156                                options.gdpr.bing_disabled_by_api = res.data.bing_disabled_by_api;
1157	                            options.gdpr.reddit_disabled_by_api = res.data.reddit_disabled_by_api;
1158
1159                                options.cookie.externalID_disabled_by_api = res.data.externalID_disabled_by_api;
1160                                options.cookie.disabled_all_cookie = res.data.disabled_all_cookie;
1161                                options.cookie.disabled_advanced_form_data_cookie = res.data.disabled_advanced_form_data_cookie;
1162                                options.cookie.disabled_landing_page_cookie = res.data.disabled_landing_page_cookie;
1163                                options.cookie.disabled_first_visit_cookie = res.data.disabled_first_visit_cookie;
1164                                options.cookie.disabled_trafficsource_cookie = res.data.disabled_trafficsource_cookie;
1165                                options.cookie.disabled_utmTerms_cookie = res.data.disabled_utmTerms_cookie;
1166                                options.cookie.disabled_utmId_cookie = res.data.disabled_utmId_cookie;
1167                            }
1168
1169                            loadPixels();
1170
1171                        }
1172                    });
1173
1174                } else {
1175                    loadPixels();
1176                }
1177
1178            },
1179
1180            consentGiven: function (pixel) {
1181
1182                /**
1183                 * ConsentMagic
1184                 */
1185                if ( options.gdpr.consent_magic_integration_enabled && typeof CS_Data !== "undefined" ) {
1186
1187                    let test_prefix = CS_Data.test_prefix;
1188                    if (
1189                        ( ( typeof CS_Data.cs_google_consent_mode_enabled !== "undefined" && CS_Data.cs_google_consent_mode_enabled == 1 ) && ( pixel == 'analytics' || pixel == 'google_ads' ) )
1190                        || ( typeof CS_Data.cs_meta_ldu_mode !== "undefined" && CS_Data.cs_meta_ldu_mode && pixel == 'facebook' )
1191                        || ( typeof CS_Data.cs_reddit_ldu_mode !== "undefined" && CS_Data.cs_reddit_ldu_mode && pixel == 'reddit' )
1192                        || ( typeof CS_Data.cs_bing_consent_mode !== "undefined" && CS_Data.cs_bing_consent_mode.ad_storage.enabled && pixel == 'bing' )
1193                    ) {
1194                        if ( CS_Data.cs_cache_enabled == 0 || ( CS_Data.cs_cache_enabled == 1 && window.CS_Cache && window.CS_Cache.check_status ) ) {
1195                            return true;
1196                        } else {
1197                            return false;
1198                        }
1199                    }
1200
1201                    if( pixel == 'facebook' && ( CS_Data.cs_script_cat.facebook == 0 || CS_Data.cs_script_cat.facebook == CS_Data.cs_necessary_cat_id ) ) {
1202                        return true;
1203                    } else if( pixel == 'bing' && ( CS_Data.cs_script_cat.bing == 0 || CS_Data.cs_script_cat.bing == CS_Data.cs_necessary_cat_id ) ) {
1204                        return true;
1205                    } else if( pixel == 'analytics' && ( CS_Data.cs_script_cat.analytics == 0 || CS_Data.cs_script_cat.analytics == CS_Data.cs_necessary_cat_id ) ) {
1206                        return true;
1207                    } else if( pixel == 'google_ads' && ( CS_Data.cs_script_cat.gads == 0 || CS_Data.cs_script_cat.gads == CS_Data.cs_necessary_cat_id ) ) {
1208                        return true;
1209                    } else if( pixel == 'pinterest' && ( CS_Data.cs_script_cat.pinterest == 0 || CS_Data.cs_script_cat.pinterest == CS_Data.cs_necessary_cat_id ) ) {
1210                        return true;
1211                    } else if( pixel == 'tiktok' && ( CS_Data.cs_script_cat.tiktok == 0 || CS_Data.cs_script_cat.tiktok == CS_Data.cs_necessary_cat_id ) ) {
1212                        return true;
1213		            } else if( pixel == 'reddit' && ( CS_Data.cs_script_cat?.reddit == 0 || CS_Data.cs_script_cat?.reddit == CS_Data.cs_necessary_cat_id ) ) {
1214		                return true;
1215		            }
1216
1217                    let substring = "cs_enabled_cookie_term",
1218                        theCookies = document.cookie.split( ';' );
1219
1220                    for ( let i = 1; i <= theCookies.length; i++ ) {
1221                        if ( theCookies[ i - 1 ].indexOf( substring ) !== -1 ) {
1222                            let categoryCookie = theCookies[ i - 1 ].replace( 'cs_enabled_cookie_term' + test_prefix + '_', '' );
1223                            categoryCookie = Number( categoryCookie.replace( /\D+/g, "" ) );
1224                            let cs_cookie_val = Cookies.get( 'cs_enabled_cookie_term' + test_prefix + '_' + categoryCookie );
1225
1226                            if ( categoryCookie === CS_Data.cs_script_cat.facebook && pixel == 'facebook' ) {
1227                                return cs_cookie_val == 'yes';
1228                            } else if ( categoryCookie === CS_Data.cs_script_cat.bing && pixel == 'bing' ) {
1229                                return cs_cookie_val == 'yes';
1230                            } else if ( categoryCookie === CS_Data.cs_script_cat.analytics && pixel == 'analytics' ) {
1231                                return cs_cookie_val == 'yes';
1232                            } else if ( categoryCookie === CS_Data.cs_script_cat.gads && pixel == 'google_ads' ) {
1233                                return cs_cookie_val == 'yes';
1234                            } else if ( categoryCookie === CS_Data.cs_script_cat.pinterest && pixel == 'pinterest' ) {
1235                                return cs_cookie_val == 'yes';
1236                            } else if ( categoryCookie === CS_Data.cs_script_cat.tiktok && pixel == 'tiktok' ) {
1237                                return cs_cookie_val == 'yes';
1238                            } else if ( categoryCookie === CS_Data.cs_script_cat?.reddit && pixel == 'reddit' ) {
1239	                            return cs_cookie_val == 'yes';
1240                            }
1241                        }
1242                    }
1243
1244                    return false;
1245                }
1246
1247                /**
1248                 * Real Cookie Banner
1249                 */
1250                if(options.gdpr.real_cookie_banner_integration_enabled) {
1251                    var consentApi = window.consentApi;
1252                    if (consentApi) {
1253                        switch (pixel) {
1254                            case "analytics":
1255                                return consentApi.consentSync("http", "_ga", "*").cookieOptIn;
1256                            case "facebook":
1257                                return consentApi.consentSync("http", "_fbp", "*").cookieOptIn;
1258                            case "pinterest":
1259                                return consentApi.consentSync("http", "_pinterest_sess", ".pinterest.com").cookieOptIn;
1260                            default:
1261                                return true;
1262                        }
1263                    }
1264                }
1265
1266                /**
1267                 * Cookiebot
1268                 */
1269                if (options.gdpr.cookiebot_integration_enabled && typeof Cookiebot !== 'undefined') {
1270
1271                    var cookiebot_consent_category = options.gdpr['cookiebot_' + pixel + '_consent_category'];
1272
1273                    if (options.gdpr[pixel + '_prior_consent_enabled']) {
1274                        if (Cookiebot.consented === true || Cookiebot.consent[cookiebot_consent_category]) {
1275                            return true;
1276                        }
1277                    } else {
1278                        if (Cookiebot.consent[cookiebot_consent_category]) {
1279                            return true;
1280                        }
1281                    }
1282
1283                    return false;
1284
1285                }
1286
1287                /**
1288                 * Cookie Notice
1289                 */
1290                if (options.gdpr.cookie_notice_integration_enabled && typeof cnArgs !== 'undefined') {
1291
1292                    var cn_cookie = Cookies.get(cnArgs.cookieName);
1293
1294                    if (options.gdpr[pixel + '_prior_consent_enabled']) {
1295                        if (typeof cn_cookie === 'undefined' || cn_cookie === 'true') {
1296                            return true;
1297                        }
1298                    } else {
1299                        if (cn_cookie === 'true') {
1300                            return true;
1301                        }
1302                    }
1303
1304                    return false;
1305
1306                }
1307
1308                /**
1309                 * Cookie Law Info
1310                 */
1311                if (options.gdpr.cookie_law_info_integration_enabled) {
1312                    var cli_cookie = Cookies.get('cookieyes-consent') ?? Cookies.get('wt_consent') ?? Cookies.get('viewed_cookie_policy');
1313                    if (options.gdpr[pixel + '_prior_consent_enabled']) {
1314                        if (typeof cli_cookie === 'undefined') return true;
1315                        if (
1316                            cli_cookie &&
1317                            (cli_cookie === Cookies.get('cookieyes-consent') || cli_cookie === Cookies.get('wt_consent'))
1318                        ) {
1319                            if (getCookieYes('analytics') === 'yes') {
1320                                return true;
1321                            }
1322                        } else if (cli_cookie && cli_cookie === Cookies.get('viewed_cookie_policy')) {
1323                            if (Cookies.get('viewed_cookie_policy') === 'yes') {
1324                                return true;
1325                            }
1326                        }
1327                    } else {
1328                        if (
1329                            cli_cookie &&
1330                            (cli_cookie === Cookies.get('cookieyes-consent') || cli_cookie === Cookies.get('wt_consent'))
1331                        ) {
1332                            if (getCookieYes('analytics') === 'yes') {
1333                                return true;
1334                            }
1335                        } else if (cli_cookie && cli_cookie === Cookies.get('viewed_cookie_policy')) {
1336                            if (Cookies.get('viewed_cookie_policy') === 'yes') {
1337                                return true;
1338                            }
1339                        }
1340                    }
1341                    return false;
1342                }
1343
1344                return true;
1345
1346            },
1347
1348            setupGdprCallbacks: function () {
1349                /**
1350                 * ConsentMagic
1351                 */
1352                if (options.gdpr.consent_magic_integration_enabled && typeof CS_Data !== "undefined") {
1353                    let test_prefix = CS_Data.test_prefix,
1354                        cs_refresh_after_consent = false,
1355                        substring = "cs_enabled_cookie_term";
1356
1357                    if (CS_Data.cs_refresh_after_consent == 1) {
1358                        cs_refresh_after_consent = CS_Data.cs_refresh_after_consent;
1359                    }
1360
1361                    let consent_actions = function () {
1362                        let theCookies = document.cookie.split( ';' );
1363
1364                        let consent = {
1365                            facebook: true,
1366                            ga: true,
1367                            google_ads: true,
1368                            tiktok: true,
1369                            bing: true,
1370                            pinterest: true,
1371                            gtm: true,
1372	                        reddit: true,
1373                        };
1374
1375                        for (let i = 1 ; i <= theCookies.length; i++) {
1376                            if (theCookies[i-1].indexOf(substring) !== -1) {
1377                                let categoryCookie = theCookies[i-1].replace('cs_enabled_cookie_term'+test_prefix+'_','');
1378                                categoryCookie = Number(categoryCookie.replace(/\D+/g,""));
1379                                let cs_cookie_val = Cookies.get('cs_enabled_cookie_term'+test_prefix+'_'+categoryCookie);
1380                                if(cs_cookie_val == 'yes') {
1381                                    if ( ( categoryCookie === CS_Data.cs_script_cat.facebook ) || ( typeof CS_Data.cs_meta_ldu_mode !== "undefined" && CS_Data.cs_meta_ldu_mode ) ) {
1382                                        Facebook.loadPixel();
1383                                    }
1384
1385                                    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 ) ) {
1386                                        Bing.loadPixel();
1387                                    }
1388
1389                                    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)
1389) {
1390
1391                                        Analytics.loadPixel();
1392                                    }
1393
1394                                    if (categoryCookie === CS_Data.cs_script_cat.pinterest) {
1395                                        Pinterest.loadPixel();
1396                                    }
1397
1398	                                if ( ( categoryCookie === CS_Data.cs_script_cat.reddit ) || ( typeof CS_Data.cs_reddit_ldu_mode !== "undefined" && CS_Data.cs_reddit_ldu_mode ) ) {
1399		                                Reddit.loadPixel();
1400	                                }
1401                                } else {
1402                                    if ( ( categoryCookie === CS_Data.cs_script_cat.facebook ) && ( typeof CS_Data.cs_meta_ldu_mode == "undefined" || !CS_Data.cs_meta_ldu_mode ) ) {
1403                                        Facebook.disable();
1404                                        consent.facebook = false;
1405                                    }
1406
1407                                    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 ) ) {
1408                                        Bing.disable();
1409                                        consent.bing = false;
1410                                    }
1411                                    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)) {
1412                                        Analytics.disable();
1413                                        consent.ga = false;
1414                                        consent.gtm = false;
1415                                    }
1416
1417                                    if (categoryCookie === CS_Data.cs_script_cat.pinterest) {
1418                                        Pinterest.disable();
1419                                        consent.pinterest = false;
1420                                    }
1421
1422	                                if ( ( categoryCookie === CS_Data.cs_script_cat.reddit ) && ( typeof CS_Data.cs_reddit_ldu_mode == "undefined" || !CS_Data.cs_reddit_ldu_mode ) ) {
1423		                                Reddit.disable();
1424		                                consent.reddit = false;
1425	                                }
1426                                }
1427                                if (Cookies.get('cs_enabled_advanced_matching') == 'yes') {
1428                                    Facebook.loadPixel();
1429                                }
1430                            }
1431                        }
1432                        Utils.setupGDPRData( consent );
1433                    }
1434
1435                    if (!cs_refresh_after_consent) {
1436                        consent_actions();
1437
1438                        $(document).on('click','.cs_action_btn',function(e) {
1439                            e.preventDefault();
1440
1441                            let consent = {
1442                                facebook: true,
1443                                ga: true,
1444                                bing: true,
1445                                pinterest: true,
1446                                gtm: true,
1447	                            reddit: true,
1448                            };
1449
1450                            let elm = $(this),
1451                                button_action = elm.attr('data-cs_action');
1452
1453                            if(button_action === 'allow_all') {
1454                                Facebook.loadPixel();
1455                                Bing.loadPixel();
1456                                Analytics.loadPixel();
1457                                Pinterest.loadPixel();
1458	                            Reddit.loadPixel();
1459
1460                                consent.facebook = true;
1461                                consent.bing = true;
1462                                consent.ga = true;
1463                                consent.pinterest = true;
1464	                            consent.reddit = true;
1465                                consent.gtm = true;
1466
1467                                Utils.setupGDPRData( consent );
1468                            } else if ( button_action === 'disable_all' ) {
1469                                if ( typeof CS_Data.cs_meta_ldu_mode == "undefined" || CS_Data.cs_meta_ldu_mode == 0 ) {
1470                                    Facebook.disable();
1471                                    consent.facebook = false;
1472                                }
1473
1474                                if ( typeof CS_Data.cs_bing_consent_mode == "undefined" || CS_Data.cs_bing_consent_mode.ad_storage.enabled == 0 ) {
1475                                    Bing.disable();
1476                                    consent.bing = false;
1477                                }
1478
1479                                if ( CS_Data.cs_google_analytics_consent_mode == 0 || typeof CS_Data.cs_google_analytics_consent_mode == "undefined" ) {
1480                                    Analytics.disable();
1481                                    consent.ga = false;
1482                                    consent.gtm = false;
1483                                }
1484
1485	                            if ( typeof CS_Data.cs_reddit_ldu_mode == "undefined" || CS_Data.cs_reddit_ldu_mode == 0 ) {
1486		                            Reddit.disable();
1487		                            consent.reddit = false;
1488	                            }
1489
1490                                Pinterest.disable();
1491                                consent.pinterest = false;
1492                                Utils.setupGDPRData( consent );
1493                            } else if ( button_action === 'cs_confirm' ) {
1494                                consent_actions();
1495                            }
1496                        });
1497                    }
1498                }
1499                /**
1500                 * Real Cookie Banner
1501                 */
1502                if(options.gdpr.real_cookie_banner_integration_enabled) {
1503                    let consentApi = window.consentApi;
1504                    if (consentApi) {
1505                        consentApi.consent("http", "_ga", "*")
1506                            .then(Analytics.loadPixel.bind(Analytics), Analytics.disable.bind(Analytics));
1507                        consentApi.consent("http", "_fbp", "*")
1508                            .then(Facebook.loadPixel.bind(Facebook), Facebook.disable.bind(Facebook));
1509                        consentApi.consent("http", "_pinterest_sess", ".pinterest.com")
1510                            .then(Pinterest.loadPixel.bind(Pinterest), Pinterest.disable.bind(Pinterest));
1511                        consentApi.consent("http", "_uetsid", "*")
1512                            .then(Bing.loadPixel.bind(Bing), Bing.disable.bind(Bing));
1513
1514                        let consent = {
1515                            facebook: true,
1516                            ga: true,
1517                            bing: true,
1518                            pinterest: true,
1519                            gtm: true,
1520                        };
1521
1522                        if (!consentApi.consentSync("http", "_ga", "*").cookieOptIn) {
1523                            consent.ga = false;
1524                            consent.gtm = false;
1525                        }
1526                        if (!consentApi.consentSync("http", "_fbp", "*").cookieOptIn) {
1527                            consent.facebook = false;
1528                        }
1529                        if (!consentApi.consentSync("http", "_pinterest_sess", ".pinterest.com").cookieOptIn) {
1530                            consent.pinterest = false;
1531                        }
1532                        if (!consentApi.consentSync("http", "_uetsid", "*").cookieOptIn) {
1533                            consent.bing = false;
1534                        }
1535                        Utils.setupGDPRData( consent );
1536                    }
1537                }
1538                /**
1539                 * Cookiebot
1540                 */
1541                if (options.gdpr.cookiebot_integration_enabled && typeof Cookiebot !== 'undefined') {
1542
1543                    window.addEventListener("CookiebotOnConsentReady", function() {
1544
1545                        let consent = {
1546                            facebook: true,
1547                            ga: true,
1548                            bing: true,
1549                            pinterest: true,
1550                            gtm: true,
1551                        };
1552
1553                        Utils.manageCookies();
1554                        if (Cookiebot.consent.marketing) {
1555                            Facebook.loadPixel();
1556                            Bing.loadPixel();
1557                            Pinterest.loadPixel();
1558
1559                            consent.facebook = true;
1560                            consent.bing = true;
1561                            consent.pinterest = true;
1562                        }
1563                        if (Cookiebot.consent.statistics) {
1564                            Analytics.loadPixel();
1565
1566                            consent.ga = true;
1567                            consent.gtm = true;
1568                        }
1569                        if (!Cookiebot.consent.marketing) {
1570                            Facebook.disable();
1571                            Pinterest.disable();
1572                            Bing.disable();
1573
1574                            consent.facebook = false;
1575                            consent.bing = false;
1576                            consent.pinterest = false;
1577                        }
1578                        if (!Cookiebot.consent.statistics) {
1579                            Analytics.disable();
1580
1581                            consent.ga = false;
1582                            consent.gtm = false;
1583                        }
1584
1585                        Utils.setupGDPRData( consent );
1586                    });
1587
1588                }
1589
1590                /**
1591                 * Cookie Notice
1592                 */
1593                if (options.gdpr.cookie_notice_integration_enabled) {
1594
1595                    $(document).onFirst('click', '.cn-set-cookie', function () {
1596
1597                        let consent = {};
1598
1599                        if ($(this).data('cookie-set') === 'accept') {
1600                            Facebook.loadPixel();
1601                            Analytics.loadPixel();
1602                            Pinterest.loadPixel();
1603                            Bing.loadPixel();
1604
1605                            consent = {
1606                                facebook: true,
1607                                ga: true,
1608                                bing: true,
1609                                pinterest: true,
1610                                gtm: true,
1611                            };
1612                        } else {
1613                            Facebook.disable();
1614                            Analytics.disable();
1615                            Pinterest.disable();
1616                            Bing.disable();
1617
1618                            consent = {
1619                                facebook: false,
1620                                ga: false,
1621                                bing: false,
1622                                pinterest: false,
1623                                gtm: false,
1624                            };
1625                        }
1626
1627                        Utils.setupGDPRData( consent );
1628                    });
1629
1630                    $(document).onFirst('click', '.cn-revoke-cookie', function () {
1631                        Facebook.disable();
1632                        Analytics.disable();
1633                        Pinterest.disable();
1634                        Bing.disable();
1635
1636                        let consent = {
1637                            facebook: false,
1638                            ga: false,
1639                            bing: false,
1640                            pinterest: false,
1641                            gtm: false,
1642                        };
1643                        Utils.setupGDPRData( consent );
1644
1645                    });
1646
1647                }
1648
1649                /**
1650                 * Cookie Law Info
1651                 */
1652                if (options.gdpr.cookie_law_info_integration_enabled) {
1653
1654                    $(document).onFirst('click', '#wt-cli-accept-all-btn,#cookie_action_close_header, .cky-btn-accept', function () {
1655                        setTimeout(function (){
1656                            let cli_cookie = Cookies.get('cookieyes-consent') ?? Cookies.get('wt_consent') ?? Cookies.get('viewed_cookie_policy');
1657                            if (typeof cli_cookie !== 'undefined') {
1658                                if (cli_cookie === Cookies.get('cookieyes-consent') || cli_cookie === Cookies.get('wt_consent')) {
1659                                    if (getCookieYes('analytics') === 'yes') {
1660                                        Utils.manageCookies();
1661                                    }
1662                                } else if (cli_cookie === Cookies.get('viewed_cookie_policy') && cli_cookie == 'yes') {
1663                                    Utils.manageCookies();
1664                                }
1665                            }
1666                        },1000)
1667                        Facebook.loadPixel();
1668                        Analytics.loadPixel();
1669                        Pinterest.loadPixel();
1670                        Bing.loadPixel();
1671
1672                        let consent = {
1673                            facebook: true,
1674                            ga: true,
1675                            bing: true,
1676                            pinterest: true,
1677                            gtm: true,
1678                        };
1679                        Utils.setupGDPRData( consent );
1680                    });
1681
1682                    $(document).onFirst('click', '#cookie_action_close_header_reject, .cky-btn-reject', function () {
1683                        Facebook.disable();
1684                        Analytics.disable();
1685                        Pinterest.disable();
1686                        Bing.disable();
1687
1688                        let consent = {
1689                            facebook: false,
1690                            ga: false,
1691                            bing: false,
1692                            pinterest: false,
1693                            gtm: false,
1694                        };
1695                        Utils.setupGDPRData( consent );
1696                    });
1697
1698                }
1699
1700            },
1701
1702            setupGDPRData: function ( consent ) {
1703                consent = window.btoa( JSON.stringify( consent ) );
1704                Cookies.set( 'pys_consent', consent, { expires: 365, path: '/', domain: domain } );
1705            },
1706
1707            /**
1708             * DOWNLOAD DOCS
1709             */
1710
1711            getLinkExtension: function (link) {
1712
1713                // Remove anchor, query string and everything before last slash
1714                link = link.substring(0, (link.indexOf("#") === -1) ? link.length : link.indexOf("#"));
1715                link = link.substring(0, (link.indexOf("?") === -1) ? link.length : link.indexOf("?"));
1716                link = link.substring(link.lastIndexOf("/") + 1, link.length);
1717
1718                // If there's a period left in the URL, then there's a extension
1719                if (link.length > 0 && link.indexOf('.') !== -1) {
1720                    link = link.substring(link.indexOf(".") + 1); // Remove everything but what's after the first period
1721                    return link;
1722                } else {
1723                    return "";
1724                }
1725            },
1726
1727            getLinkFilename: function (link) {
1728
1729                // Remove anchor, query string and everything before last slash
1730                link = link.substring(0, (link.indexOf("#") === -1) ? link.length : link.indexOf("#"));
1731                link = link.substring(0, (link.indexOf("?") === -1) ? link.length : link.indexOf("?"));
1732                link = link.substring(link.lastIndexOf("/") + 1, link.length);
1733
1734                // If there's a period left in the URL, then there's a extension
1735                if (link.length > 0 && link.indexOf('.') !== -1) {
1736                    return link;
1737                } else {
1738                    return "";
1739                }
1740            },
1741            /**
1742             * Enrich
1743             */
1744            isCheckoutPage: function () {
1745                return $('body').hasClass('woocommerce-checkout') || document.querySelector('.woocommerce-checkout') ||
1746                    $('body').hasClass('edd-checkout');
1747            },
1748            addCheckoutFields : function() {
1749                var utm = "";
1750                var utms = getUTMs()
1751
1752                $.each(utmTerms, function (index, name) {
1753                    if(index > 0) {
1754                        utm+="|";
1755                    }
1756                    utm+=name+":"+utms[name];
1757                });
1758                var utmIdList = "";
1759                var utmsIds = getUTMId()
1760                $.each(utmId, function (index, name) {
1761                    if(index > 0) {
1762                        utmIdList+="|";
1763                    }
1764                    utmIdList+=name+":"+utmsIds[name];
1765                });
1766                var utmIdListLast = "";
1767                var utmsIdsLast = getUTMId(true)
1768                $.each(utmId, function (index, name) {
1769                    if(index > 0) {
1770                        utmIdListLast+="|";
1771                    }
1772                    utmIdListLast+=name+":"+utmsIdsLast[name];
1773                });
1774
1775
1776                var utmLast = "";
1777                var utmsLast = getUTMs(true)
1778                $.each(utmTerms, function (index, name) {
1779                    if(index > 0) {
1780                        utmLast+="|";
1781                    }
1782                    utmLast+=name+":"+utmsLast[name];
1783                });
1784
1785                var dateTime = getDateTime();
1786                var landing = getLandingPageValue();
1787                var lastLanding = getLandingPageValue();
1788                var trafic = getTrafficSourceValue();
1789                var lastTrafic = getTrafficSourceValue();
1790
1791                var $form = null;
1792                if($('body').hasClass('woocommerce-checkout')) {
1793                    $form = $("form.woocommerce-checkout");
1794                } else {
1795                    $form = $("#edd_purchase_form");
1796                }
1797                var inputs = {'pys_utm':utm,
1798                    'pys_utm_id':utmIdList,
1799                    'pys_browser_time':dateTime.join("|"),
1800                    'pys_landing':landing,
1801                    'pys_source':trafic,
1802                    'pys_order_type': $(".wcf-optin-form").length > 0 ? "wcf-optin" : "normal",
1803
1804                    'last_pys_landing':lastLanding,
1805                    'last_pys_source':lastTrafic,
1806                    'last_pys_utm':utmLast,
1807                    'last_pys_utm_id':utmIdListLast,
1808                }
1809
1810                Object.keys(inputs).forEach(function(key,index) {
1811                    $form.append("<input type='hidden' name='"+key+"' value='"+inputs[key]+"' /> ");
1812                });
1813
1814
1815            },
1816            getAdvancedFormData: function () {
1817                let dataStr = Cookies.get("pys_advanced_form_data");
1818                if(dataStr === undefined) {
1819                    return {'first_name':"",'last_name':"",'email':"",'phone':""};
1820                } else {
1821                    return JSON.parse(dataStr);
1822                }
1823            },
1824            getFormFilledData: function ( event ) {
1825                // First, resolve static/dynamic parameters
1826                if (event.params && Object.keys(event.params).length > 0) {
1827                    Object.entries(event.params).forEach(([key, value]) => {
1828                        // Resolve parameter value (static or dynamic)
1829                        const resolvedValue = resolveParamValue(value);
1830                        if (resolvedValue !== null) {
1831                            event.params[key] = resolvedValue;
1832                        }
1833                    });
1834                }
1835                return event;
1836            }
1837        };
1838
1839    }(options);
1840
1841    var Facebook = function (options) {
1842
1843
1844        var defaultEventTypes = [
1845            'PageView',
1846            'ViewContent',
1847            'Search',
1848            'AddToCart',
1849            'AddToWishlist',
1850            'InitiateCheckout',
1851            'AddPaymentInfo',
1852            'Purchase',
1853            'Lead',
1854
1855            'Subscribe',
1856            'CustomizeProduct',
1857            'FindLocation',
1858            'StartTrial',
1859            'SubmitApplication',
1860            'Schedule',
1861            'Contact',
1862            'Donate'
1863        ];
1864
1865        var initialized = false;
1866        var genereateFbp = function (){
1867            return !Cookies.get('_fbp') ? 'fb.1.'+Date.now()+'.'+Math.floor(1000000000 + Math.random() * 9000000000) : Cookies.get('_fbp');
1868        };
1869        var genereateFbc = function (){
1870            return getUrlParameter('fbclid') ? 'fb.1.'+Date.now()+'.'+getUrlParameter('fbclid') : ''
1871        };
1872        // fire server side event gdpr plugin installed
1873        var isApiDisabled = options.gdpr.all_disabled_by_api ||
1874            options.gdpr.facebook_disabled_by_api ||
1875            options.gdpr.cookiebot_integration_enabled ||
1876            options.gdpr.consent_magic_integration_enabled ||
1877            options.gdpr.cookie_notice_integration_enabled ||
1878            options.gdpr.cookie_law_info_integration_enabled;
1879
1880        /**
1881         *
1882         * @param allData
1883         * @param params
1884         * @returns {string | null}
1885         */
1886        function sendFbServerEvent(allData,name,params) {
1887            let eventId = null;
1888            if(options.facebook.serverApiEnabled) {
1889
1890                if(allData.e_id === "woo_remove_from_cart") {// server event will sended from hook
1891                    Facebook.updateEventId(allData.name);
1892                    allData.eventID = Facebook.getEventId(allData.name);
1893                } else {
1894                    // send event from server if they was bloc by gdpr or need send with delay
1895                    allData.eventID = Utils.generateUniqueId(allData);
1896
1897                    if(Cookies.get('_fbp')){
1898                        params._fbp = Cookies.get('_fbp');
1899                    }
1900                    if(Cookies.get('_fbc')){
1901                        params._fbc = Cookies.get('_fbc');
1902                    }
1903
1904                    if( options.ajaxForServerEvent || isApiDisabled ){
1905                        var json = {
1906                            action: 'pys_api_event',
1907                            pixel: 'facebook',
1908                            event: name,
1909                            data:params,
1910                            ids:options.facebook.pixelIds,
1911                            eventID:allData.eventID,
1912                            url:window.location.href,
1913                            ajax_event:options.ajax_event
1914                        };
1915                        if(allData.hasOwnProperty('woo_order')) {
1916                            json['woo_order'] = allData.woo_order;
1917                        }
1918                        if(allData.hasOwnProperty('edd_order')) {
1919                            json['edd_order'] = allData.edd_order;
1920                        }
1921
1922                        if (allData.e_id === "automatic_event_internal_link" || allData.e_id === "automatic_event_outbound_link") {
1923                            setTimeout(() => Utils.sendServerAjaxRequest(options.ajaxUrl, json), 500);
1924                        } else if (allData.type != 'static') {
1925                            Utils.sendServerAjaxRequest(options.ajaxUrl, json);
1926                        }
1927
1928                        if ( ( allData.type == 'static' && options.ajaxForServerStaticEvent ) || ( allData.hasOwnProperty( 'ajaxFire' ) && allData.ajaxFire ) ) {
1929                            Utils.sendServerAjaxRequest( options.ajaxUrl, json );
1930                        }
1931                    }
1932                }
1933                delete params._fbp;
1934                delete params._fbc;
1935                eventId = allData.eventID
1936            }
1937            return eventId;
1938        }
1939
1940        function fireEvent(name, allData) {
1941
1942            if(typeof window.pys_event_data_filter === "function" && window.pys_disable_event_filter(name,'facebook')) {
1943                return;
1944            }
1945
1946            var actionType = defaultEventTypes.includes(name) ? 'track' : 'trackCustom';
1947            var data = allData.params;
1948            var params = {};
1949            var arg = {};
1950            Utils.copyProperties(data, params);
1951            let eventId = sendFbServerEvent(allData,name,params)
1952
1953
1954            if("hCR" === name) {
1955                return;
1956            }
1957
1958            if (options.debug) {
1959                console.log('[Facebook] ' + name, params,"eventID",eventId);
1960            }
1961
1962            if(eventId != null) {
1963                arg.eventID = eventId;
1964            }
1965
1966            fbq(actionType, name, params, arg);
1967
1968        }
1969
1970        /**
1971         * Public API
1972         */
1973        return {
1974            tag: function() {
1975                return "facebook";
1976            },
1977            isEnabled: function () {
1978                return options.hasOwnProperty('facebook');
1979            },
1980
1981            disable: function () {
1982                initialized = false;
1983            },
1984            advancedMatching: function () {
1985                if(options.facebook.advancedMatchingEnabled) {
1986                    let advancedMatchingForm = Utils.getAdvancedFormData();
1987                    let advancedMatching = {};
1988                    if(Object.keys(options.facebook.advancedMatching).length > 0) {
1989                        advancedMatching = options.facebook.advancedMatching;
1990                    }
1991
1992                    if(!advancedMatching.hasOwnProperty("em")
1993                        && advancedMatchingForm.hasOwnProperty("email") && advancedMatchingForm["email"].length > 0) {
1994                        advancedMatching["em"] = advancedMatchingForm["email"];
1995                    }
1996                    if(!advancedMatching.hasOwnProperty("ph")
1997                        && advancedMatchingForm.hasOwnProperty("phone") && advancedMatchingForm["phone"].length > 0) {
1998                        advancedMatching["ph"] = advancedMatchingForm["phone"];
1999                    }
2000                    if(!advancedMatching.hasOwnProperty("fn")
2001                        && advancedMatchingForm.hasOwnProperty("first_name") && advancedMatchingForm["first_name"].length > 0) {
2002                        advancedMatching["fn"] = advancedMatchingForm["first_name"];
2003                    }
2004                    if(!advancedMatching.hasOwnProperty("ln")
2005                        && advancedMatchingForm.hasOwnProperty("last_name") && advancedMatchingForm["last_name"].length > 0) {
2006                        advancedMatching["ln"] = advancedMatchingForm["last_name"];
2007                    }
2008                    if(!advancedMatching.hasOwnProperty("external_id")){
2009                        if (Cookies.get('pbid') || (options.hasOwnProperty('pbid') && options.pbid)) {
2010                            advancedMatching["external_id"] = Cookies.get('pbid') ? Cookies.get('pbid') : options.pbid;
2011                        }
2012                    }
2013                    else if(advancedMatching.external_id != Cookies.get('pbid'))
2014                    {
2015                        advancedMatching["external_id"] = Cookies.get('pbid') ? Cookies.get('pbid') : advancedMatching.external_id;
2016                    }
2017                    if(Object.keys(advancedMatching).length > 0) {
2018                        return advancedMatching;
2019                    }
2020                }
2021                return false
2022            },
2023            /**
2024             * Load pixel's JS
2025             */
2026            loadPixel: function () {
2027
2028                if (initialized || !this.isEnabled() || !Utils.consentGiven('facebook')) {
2029                    return;
2030                }
2031
2032                !function (f, b, e, v, n, t, s) {
2033                    if (f.fbq) return;
2034                    n = f.fbq = function () {
2035                        n.callMethod ?
2036                            n.callMethod.apply(n, arguments) : n.queue.push(arguments)
2037                    };
2038                    if (!f._fbq) f._fbq = n;
2039                    n.push = n;
2040                    n.loaded = !0;
2041                    n.version = '2.0';
2042                    n.agent = 'dvpixelyoursite';
2043                    n.queue = [];
2044                    t = b.createElement(e);
2045                    t.async = !0;
2046                    t.src = v;
2047                    s = b.getElementsByTagName(e)[0];
2048                    s.parentNode.insertBefore(t, s)
2049                }(window,
2050                    document, 'script', 'https://connect.facebook.net/en_US/fbevents.js');
2051
2052                let expires = parseInt(options.cookie_duration);
2053                if(!Cookies.get('_fbp')) {
2054                    Cookies.set('_fbp',genereateFbp(),  { expires: expires,path: '/',domain: domain });
2055                }
2056
2057                if(getUrlParameter('fbclid')) {
2058                    Cookies.set('_fbc',genereateFbc(),  { expires: expires,path: '/',domain: domain });
2059                }
2060                // initialize pixel
2061                options.facebook.pixelIds.forEach(function (pixelId) {
2062                    if (options.facebook.removeMetadata) {
2063                        fbq('set', 'autoConfig', false, pixelId);
2064                    }
2065                    let advancedMatching = Facebook.advancedMatching();
2066
2067                    if ( +options.facebook.meta_ldu === 1  ) {
2068                        fbq( 'dataProcessingOptions', [ 'LDU' ], 0, 0 );
2069                    }
2070
2071                    if (options.gdpr.consent_magic_integration_enabled && typeof CS_Data !== "undefined") {
2072                        if(!advancedMatching) {
2073                            fbq('init', pixelId);
2074                        } else {
2075                            var test_prefix = CS_Data.test_prefix;
2076                            var cs_advanced_matching = Cookies.get('cs_enabled_advanced_matching'+test_prefix);
2077                            if (jQuery('#cs_enabled_advanced_matching'+test_prefix).length > 0) {
2078                                if (cs_advanced_matching == 'yes') {
2079                                    fbq('init', pixelId, advancedMatching);
2080                                } else {
2081                                    fbq('init', pixelId);
2082                                }
2083                            } else {
2084                                fbq('init', pixelId, advancedMatching);
2085                            }
2086                        }
2087                    } else {
2088                        if(!advancedMatching) {
2089                            fbq('init', pixelId);
2090                        }  else {
2091                            fbq('init', pixelId, advancedMatching);
2092                        }
2093                    }
2094                });
2095
2096                initialized = true;
2097
2098                Utils.fireStaticEvents('facebook');
2099
2100            },
2101
2102            fireEvent: function (name, data) {
2103
2104                if (!initialized || !this.isEnabled()) {
2105                    return false;
2106                }
2107
2108                data.delay = data.delay || 0;
2109                data.params = data.params || {};
2110
2111                if (data.delay === 0) {
2112
2113                    fireEvent(name, data);
2114
2115                } else {
2116
2117                    setTimeout(function (name, params) {
2118                        fireEvent(name, params);
2119                    }, data.delay * 1000, name, data);
2120
2121                }
2122
2123                return true;
2124
2125            },
2126
2127            onCommentEvent: function (event) {
2128                this.fireEvent(event.name, event);
2129            },
2130
2131            onDownloadEvent: function (event) {
2132                this.fireEvent(event.name, event);
2133            },
2134
2135            onFormEvent: function (event) {
2136
2137                this.fireEvent(event.name, event);
2138
2139            },
2140
2141            onWooAddToCartOnButtonEvent: function (product_id) {
2142
2143                if(!options.dynamicEvents.woo_add_to_cart_on_button_click.hasOwnProperty(this.tag()))
2144                    return;
2145                var event = options.dynamicEvents.woo_add_to_cart_on_button_click[this.tag()];
2146                window.pysWooProductData = window.pysWooProductData || [];
2147                if (window.pysWooProductData.hasOwnProperty(product_id)) {
2148                    if (window.pysWooProductData[product_id].hasOwnProperty('facebook')) {
2149                        event = Utils.copyProperties(event, {})
2150                        Utils.copyProperties(window.pysWooProductData[product_id]['facebook'].params, event.params)
2151                        this.fireEvent(event.name, event);
2152                    }
2153                }
2154            },
2155
2156            onWooAddToCartOnSingleEvent: function (product_id, qty, product_type, $form) {
2157
2158                window.pysWooProductData = window.pysWooProductData || [];
2159                if(!options.dynamicEvents.woo_add_to_cart_on_button_click.hasOwnProperty(this.tag()))
2160                    return;
2161                var event = Utils.clone(options.dynamicEvents.woo_add_to_cart_on_button_click[this.tag()]);
2162
2163                if (product_type === Utils.PRODUCT_VARIABLE && !options.facebook.wooVariableAsSimple) {
2164                    product_id = parseInt($form.find('input[name="variation_id"]').val());
2165                }
2166
2167                if (window.pysWooProductData.hasOwnProperty(product_id)) {
2168                    if (window.pysWooProductData[product_id].hasOwnProperty('facebook')) {
2169
2170
2171                        Utils.copyProperties(window.pysWooProductData[product_id]['facebook'].params, event.params);
2172
2173                        var groupValue = 0;
2174                        if(product_type === Utils.PRODUCT_GROUPED ) {
2175                            $form.find(".woocommerce-grouped-product-list .qty").each(function(index){
2176                                var childId = $(this).attr('name').replaceAll("quantity[","").replaceAll("]","");
2177                                var quantity = parseInt($(this).val());
2178                                if(isNaN(quantity)) {
2179                                    quantity = 0;
2180                                }
2181                                var childItem = window.pysWooProductData[product_id]['facebook'].grouped[childId];
2182
2183                                if(quantity == 0) {
2184                                    event.params.content_ids.forEach(function(el,index,array) {
2185                                        if(el == childItem.content_id) {
2186                                            array.splice(index, 1);
2187                                        }
2188                                    });
2189                                }
2190
2191                                if(event.params.hasOwnProperty('contents')) {
2192                                    event.params.contents.forEach(function(el,index,array) {
2193                                        if(el.id == childItem.content_id) {
2194                                            if(quantity > 0){
2195                                                el.quantity = quantity;
2196                                            } else {
2197                                                array.splice(index, 1);
2198                                            }
2199                                        }
2200                                    });
2201                                }
2202
2203
2204                                groupValue += childItem.price * quantity;
2205                            });
2206                            if(groupValue == 0) return;
2206 // skip if no items selected
2207                        }
2208
2209                        // maybe customize value option
2210                        if (options.woo.addToCartOnButtonValueEnabled && options.woo.addToCartOnButtonValueOption !== 'global') {
2211
2212                            if(product_type === Utils.PRODUCT_GROUPED) {
2213                                event.params.value = groupValue;
2214                            } else if(product_type === Utils.PRODUCT_BUNDLE) {
2215                                var data = $(".bundle_form .bundle_data").data("bundle_form_data");
2216                                var items_sum = getBundlePriceOnSingleProduct(data);
2217                                event.params.value = (parseInt(data.base_price) + items_sum )* qty;
2218                            } else {
2219                                event.params.value = event.params.value * qty;
2220                            }
2221                        }
2222
2223                        // only when non Facebook for WooCommerce logic used
2224                        if (event.params.hasOwnProperty('contents') && product_type !== Utils.PRODUCT_GROUPED) {
2225                            event.params.contents[0].quantity = qty;
2226                        }
2227
2228                        this.fireEvent(event.name, event);
2229
2230                    }
2231                }
2232            },
2233
2234            onWooRemoveFromCartEvent: function (event) {
2235                this.fireEvent(event.name, event);
2236            },
2237
2238            onEddAddToCartOnButtonEvent: function (download_id, price_index, qty) {
2239
2240                if(!options.dynamicEvents.edd_add_to_cart_on_button_click.hasOwnProperty(this.tag()))
2241                    return;
2242                var event = Utils.clone(options.dynamicEvents.edd_add_to_cart_on_button_click[this.tag()]);
2243
2244                if (window.pysEddProductData.hasOwnProperty(download_id)) {
2245
2246                    var index;
2247
2248                    if (price_index) {
2249                        index = download_id + '_' + price_index;
2250                    } else {
2251                        index = download_id;
2252                    }
2253
2254                    if (window.pysEddProductData[download_id].hasOwnProperty(index)) {
2255                        if (window.pysEddProductData[download_id][index].hasOwnProperty('facebook')) {
2256
2257
2258                            Utils.copyProperties(window.pysEddProductData[download_id][index]['facebook']["params"], event.params)
2259
2260                            // maybe customize value option
2261                            if (options.edd.addToCartOnButtonValueEnabled && options.edd.addToCartOnButtonValueOption !== 'global') {
2262                                event.params.value = event.params.value * qty;
2263                            }
2264
2265                            // update contents qty param
2266                            var contents = event.params.contents;
2267                            contents[0].quantity = qty;
2268                            event.params.contents = contents;
2269
2270                            this.fireEvent(event.name,event);
2271
2272                        }
2273                    }
2274
2275                }
2276
2277            },
2278
2279            onEddRemoveFromCartEvent: function (event) {
2280                this.fireEvent(event.name, event);
2281            },
2282            onPageScroll: function (event) {
2283                this.fireEvent(event.name, event);
2284            },
2285            onTime: function (event) {
2286                this.fireEvent(event.name, event);
2287            },
2288            initEventIdCookies: function (key) {
2289                var ids = {};
2290                ids[key] = pys_generate_token(36)
2291                Cookies.set('pys_fb_event_id', JSON.stringify(ids));
2292            },
2293            updateEventId:function(key) {
2294                var cooData = Cookies.get("pys_fb_event_id")
2295                if(cooData === undefined) {
2296                    this.initEventIdCookies(key);
2297                } else {
2298                    var data = JSON.parse(cooData);
2299                    data[key] = pys_generate_token(36);
2300                    Cookies.set('pys_fb_event_id', JSON.stringify(data) );
2301                }
2302            },
2303
2304            getEventId:function (key) {
2305                var data = Cookies.get("pys_fb_event_id");
2306                if(data === undefined) {
2307                    this.initEventIdCookies(key);
2308                    data = Cookies.get("pys_fb_event_id");
2309                }
2310                return JSON.parse(data)[key];
2311            },
2312
2313            sendFacebookRestAPIRequest: function(allData, name, params) {
2314                if (typeof window.pysFacebookRest === 'undefined' || !window.pysFacebookRest.restApiUrl) {
2315                    return;
2316                }
2317
2318                const restApiData = {
2319                    event: name,
2320                    data: JSON.stringify(params),
2321                    ids: allData.pixelIds || options.facebook.pixelIds,
2322                    eventID: allData.eventID,
2323                    woo_order: allData.woo_order || 0,
2324                    edd_order: allData.edd_order || 0
2325                };
2326
2327                // Try sendBeacon first
2328                if (navigator.sendBeacon) {
2329                    const formData = new FormData();
2330                    Object.keys(restApiData).forEach(key => {
2331                        if (Array.isArray(restApiData[key])) {
2332                            restApiData[key].forEach(value => {
2333                                formData.append(key + '[]', value);
2334                            });
2335                        } else {
2336                            formData.append(key, restApiData[key]);
2337                        }
2338                    });
2339
2340                    if (navigator.sendBeacon(window.pysFacebookRest.restApiUrl, formData)) {
2341                        return;
2342                    }
2343                }
2344
2345                // Fallback to fetch
2346                fetch(window.pysFacebookRest.restApiUrl, {
2347                    method: 'POST',
2348                    headers: {
2349                        'Content-Type': 'application/x-www-form-urlencoded',
2350                    },
2351                    body: new URLSearchParams(restApiData)
2352                }).catch(() => {
2353                    // Fallback to AJAX if fetch fails
2354                    this.sendAjaxFallback(allData, name, params);
2355                });
2356            },
2357
2358            sendAjaxFallback: function(allData, name, params) {
2359                var json = {
2360                    action: 'pys_api_event',
2361                    pixel: 'facebook',
2362                    event: name,
2363                    data: params,
2364                    ids: allData.pixelIds || options.facebook.pixelIds,
2365                    eventID: allData.eventID,
2366                    url: window.location.href,
2367                    ajax_event: options.ajax_event
2368                };
2369                if (allData.hasOwnProperty('woo_order')) {
2370                    json['woo_order'] = allData.woo_order;
2371                }
2372                if (allData.hasOwnProperty('edd_order')) {
2373                    json['edd_order'] = allData.edd_order;
2374                }
2375
2376                Utils.sendServerAjaxRequest(options.ajaxUrl, json);
2377            },
2378        };
2379
2380    }(options);
2381
2382    var Analytics = function (options) {
2383
2384        var initialized = false;
2385
2386        /**
2387         * Fires event
2388         *
2389         * @link: https://developers.google.com/analytics/devguides/collection/gtagjs/sending-data
2390         * @link: https://developers.google.com/analytics/devguides/collection/gtagjs/events
2391         * @link: https://developers.google.com/gtagjs/reference/event
2392         * @link: https://developers.google.com/gtagjs/reference/parameter
2393         *
2394         * @link: https://developers.google.com/analytics/devguides/collection/gtagjs/custom-dims-mets
2395         *
2396         * @param name
2397         * @param data
2398         */
2399        function fireEvent(name, data) {
2400
2401            if(typeof window.pys_event_data_filter === "function" && window.pys_disable_event_filter(name,'ga')) {
2402                return;
2403            }
2404
2405            var eventParams = Utils.copyProperties(data, {});
2406            var _fireEvent = function (tracking_id,name,params) {
2407
2408                params['send_to'] = tracking_id;
2409
2410                if (options.debug) {
2411                    console.log('[Google Analytics #' + tracking_id + '] ' + name, params);
2412                }
2413
2414                gtag('event', name, params);
2415
2416            };
2417            options.ga.trackingIds.forEach(function (tracking_id) {
2418                var copyParams = Utils.copyProperties(eventParam
2418s, {}); // copy params because mapParamsTov4 can modify it
2419                var params = mapParamsTov4(tracking_id,name,copyParams)
2420                _fireEvent(tracking_id,name,params);
2421            });
2422
2423        }
2424        function mapParamsTov4(tag,name,param) {
2425            //GA4 automatically collects a number of parameters for all events
2426            delete param.landing_page;
2427            // end
2428            if(isv4(tag)) {
2429                delete param.traffic_source;
2430                delete param.event_category;
2431                delete param.event_label;
2432                delete param.ecomm_prodid;
2433                delete param.ecomm_pagetype;
2434                delete param.ecomm_totalvalue;
2435                if(name === 'search') {
2436                    param['search'] = param.search_term;
2437                    delete param.search_term;
2438                    delete param.dynx_itemid;
2439                    delete param.dynx_pagetype;
2440                    delete param.dynx_totalvalue;
2441                }
2442            }
2443            return param;
2444        }
2445
2446        function isv4(tag) {
2447            return tag.indexOf('G') === 0;
2448        }
2449
2450        /**
2451         * Public API
2452         */
2453        return {
2454            tag: function() {
2455                return "ga";
2456            },
2457            isEnabled: function () {
2458                return options.hasOwnProperty('ga');
2459            },
2460
2461            disable: function () {
2462                initialized = false;
2463            },
2464
2465            loadPixel: function () {
2466
2467                if (initialized || !this.isEnabled() || !Utils.consentGiven('analytics')) {
2468                    return;
2469                }
2470
2471                Utils.loadGoogleTag(options.ga.trackingIds[0]);
2472                var config = {};
2473                // Cross-Domain tracking
2474                if (options.ga.crossDomainEnabled) {
2475                    config.linker = {
2476                        accept_incoming: options.ga.crossDomainAcceptIncoming,
2477                        domains: options.ga.crossDomainDomains
2478                    };
2479                }
2480                var ids = options.ga.trackingIds;
2481                // configure tracking ids
2482                ids.forEach(function (trackingId,index) {
2483                    var obj = options.ga.isDebugEnabled;
2484                    var searchValue = "index_"+index;
2485                    var config_for_tag = Object.assign({}, options.config);
2486                    config_for_tag.debug_mode = false;
2487                    config_for_tag.send_page_view = !options.ga.custom_page_view_event;
2488                    for (var key in obj) {
2489                        if (obj.hasOwnProperty(key) && obj[key] === searchValue) {
2490                            config_for_tag.debug_mode = true;
2491                            break;
2492                        }
2493                    }
2494                    if(!config_for_tag.debug_mode)
2495                    {
2496                        delete config_for_tag.debug_mode;
2497                    }
2498                    if(isv4(trackingId)) {
2499                        if(options.ga.disableAdvertisingFeatures) {
2500                            config_for_tag.allow_google_signals = false
2501                        }
2502                        if(options.ga.disableAdvertisingPersonalization) {
2503                            config_for_tag.allow_ad_personalization_signals = false
2504                        }
2505                    }
2506                    if(options.ga.hasOwnProperty('additionalConfig')){
2507                        if(options.ga.additionalConfig.hasOwnProperty(trackingId) && options.ga.additionalConfig[trackingId]){
2508                            config_for_tag.first_party_collection = options.ga.additionalConfig[trackingId].first_party_collection;
2509                        }
2510
2511                    }
2512                    if(options.ga.hasOwnProperty('serverContainerUrls')){
2513                        if(options.ga.serverContainerUrls.hasOwnProperty(trackingId) && options.ga.serverContainerUrls[trackingId].enable_server_container != false){
2514                            if(options.ga.serverContainerUrls[trackingId].server_container_url != ''){
2515                                config_for_tag.server_container_url = options.ga.serverContainerUrls[trackingId].server_container_url;
2516                            }
2517                            if(options.ga.serverContainerUrls[trackingId].transport_url != ''){
2518                                config_for_tag.transport_url = options.ga.serverContainerUrls[trackingId].transport_url;
2519                            }
2520                        }
2521                    }
2522                    if (options.gdpr.cookiebot_integration_enabled && typeof Cookiebot !== 'undefined') {
2523
2524                        var cookiebot_consent_category = options.gdpr['cookiebot_analytics_consent_category'];
2525                        if (options.gdpr['analytics_prior_consent_enabled']) {
2526                            if (Cookiebot.consented === true && Cookiebot.consent[cookiebot_consent_category]) {
2527                                gtag('config', trackingId, config_for_tag);
2528                            }
2529                        } else {
2530                            if (Cookiebot.consent[cookiebot_consent_category]) {
2531                                gtag('config', trackingId, config_for_tag);
2532                            }
2533                        }
2534                    }
2535                    else
2536                    {
2537                        gtag('config', trackingId, config_for_tag);
2538                    }
2539                });
2540
2541                initialized = true;
2542
2543                Utils.fireStaticEvents('ga');
2544
2545            },
2546
2547            fireEvent: function (name, data) {
2548
2549                if (!initialized || !this.isEnabled()) {
2550                    return false;
2551                }
2552
2553                data.delay = data.delay || 0;
2554                data.params = data.params || {};
2555                data.params.eventID = Utils.generateUniqueId(data);
2556                if (data.delay === 0) {
2557
2558                    fireEvent(name, data.params);
2559
2560                } else {
2561
2562                    setTimeout(function (name, params) {
2563                        fireEvent(name, params);
2564                    }, data.delay * 1000, name, data.params);
2565
2566                }
2567
2568                return true;
2569
2570            },
2571
2572            onCommentEvent: function (event) {
2573                this.fireEvent(event.name, event);
2574            },
2575
2576            onDownloadEvent: function (event) {
2577                this.fireEvent(event.name, event);
2578            },
2579
2580            onFormEvent: function (event) {
2581                this.fireEvent(event.name, event);
2582            },
2583
2584            onWooAddToCartOnButtonEvent: function (product_id) {
2585
2586                if(!options.dynamicEvents.woo_add_to_cart_on_button_click.hasOwnProperty(this.tag()))
2587                    return;
2588                var event = Utils.clone(options.dynamicEvents.woo_add_to_cart_on_button_click[this.tag()]);
2589
2590                if (window.pysWooProductData.hasOwnProperty(product_id)) {
2591                    if (window.pysWooProductData[product_id].hasOwnProperty('ga')) {
2592                        Utils.copyProperties(window.pysWooProductData[product_id]['ga'].params, event.params)
2593                        this.fireEvent(event.name, event);
2594                    }
2595                }
2596
2597
2598            },
2599
2600            onWooAddToCartOnSingleEvent: function (product_id, qty, product_type, $form) {
2601
2602                window.pysWooProductData = window.pysWooProductData || [];
2603
2604                if(!options.dynamicEvents.woo_add_to_cart_on_button_click.hasOwnProperty(this.tag()))
2605                    return;
2606                var event = Utils.clone(options.dynamicEvents.woo_add_to_cart_on_button_click[this.tag()]);
2607
2608                if (product_type === Utils.PRODUCT_VARIABLE && !options.ga.wooVariableAsSimple) {
2609                    product_id = parseInt($form.find('input[name="variation_id"]').val());
2610                }
2611
2612                if (window.pysWooProductData.hasOwnProperty(product_id)) {
2613                    if (window.pysWooProductData[product_id].hasOwnProperty('ga')) {
2614
2615                        Utils.copyProperties(window.pysWooProductData[product_id]['ga'].params, event.params);
2616                        if(product_type === Utils.PRODUCT_GROUPED ) {
2617                            var groupValue = 0;
2618                            $form.find(".woocommerce-grouped-product-list .qty").each(function(index){
2619                                var childId = $(this).attr('name').replaceAll("quantity[","").replaceAll("]","");
2620                                var quantity = parseInt($(this).val());
2621                                if(isNaN(quantity)) {
2622                                    quantity = 0;
2623                                }
2624                                var childItem = window.pysWooProductData[product_id]['ga'].grouped[childId];
2625                                // update quantity
2626                                event.params.items.forEach(function(el,index,array) {
2627                                    if(el.id == childItem.content_id) {
2628                                        if(quantity > 0){
2629                                            el.quantity = quantity;
2630                                        } else {
2631                                            array.splice(index, 1);
2632                                        }
2633                                    }
2634                                });
2635                                groupValue += childItem.price * quantity;
2636                            });
2637                            if(options.woo.addToCartOnButtonValueEnabled &&
2638                                options.woo.addToCartOnButtonValueOption !== 'global' &&
2639                                event.params.hasOwnProperty('ecomm_totalvalue')) {
2640                                event.params.ecomm_totalvalue = groupValue;
2641                            }
2642
2643                            if(groupValue == 0) return; // skip if no items selected
2644                        } else {
2645                            // update items qty param
2646                            event.params.items[0].quantity = qty;
2647                        }
2648
2649                        // maybe customize value option
2650                        if (options.woo.addToCartOnButtonValueEnabled &&
2651                            options.woo.addToCartOnButtonValueOption !== 'global' &&
2652                            product_type !== Utils.PRODUCT_GROUPED)
2653                        {
2654                            if(event.params.hasOwnProperty('ecomm_totalvalue')) {
2655                                event.params.ecomm_totalvalue = event.params.items[0].price * qty;
2656                            }
2657
2658                        }
2659
2660
2661                        this.fireEvent(event.name, event);
2662                    }
2663                }
2664
2665            },
2666
2667            onWooRemoveFromCartEvent: function (event) {
2668
2669                this.fireEvent(event.name, event);
2670
2671            },
2672
2673            onEddAddToCartOnButtonEvent: function (download_id, price_index, qty) {
2674
2675                if(!options.dynamicEvents.edd_add_to_cart_on_button_click.hasOwnProperty(this.tag()))
2676                    return;
2677                var event = Utils.clone(options.dynamicEvents.edd_add_to_cart_on_button_click[this.tag()]);
2678
2679
2680                if (window.pysEddProductData.hasOwnProperty(download_id)) {
2681
2682                    var index;
2683
2684                    if (price_index) {
2685                        index = download_id + '_' + price_index;
2686                    } else {
2687                        index = download_id;
2688                    }
2689
2690                    if (window.pysEddProductData[download_id].hasOwnProperty(index)) {
2691                        if (window.pysEddProductData[download_id][index].hasOwnProperty('ga')) {
2692
2693                            Utils.copyProperties(window.pysEddProductData[download_id][index]['ga'].params, event.params);
2694
2695                            // update items qty param
2696                            event.params.items[0].quantity = qty;
2697
2698                            this.fireEvent(event.name,event);
2699
2700                        }
2701                    }
2702
2703                }
2704
2705            },
2706
2707            onEddRemoveFromCartEvent: function (event) {
2708                this.fireEvent(event.name, event);
2709            },
2710            onPageScroll: function (event) {
2711                this.fireEvent(event.name, event);
2712            },
2713            onTime: function (event) {
2714                this.fireEvent(event.name, event);
2715            },
2716
2717        };
2718
2719    }(options);
2720
2721    var GTM = function (options) {
2722        var initialized = false;
2723
2724        var datalayer_name = 'dataLayer';
2725        /*
2726         * @param name
2727         * @param data
2728         */
2729        function fireEvent(name, event) {
2730            if(typeof window.pys_event_data_filter === "function" && window.pys_disable_event_filter(name,'gtm')) {
2731                return;
2732            }
2733
2734
2735            var eventParams = event.params;
2736            var data = event.params;
2737            var valuesArray = Object.values(event.trackingIds);
2738            var ids = valuesArray;
2739            Utils.copyProperties(Utils.getRequestParams(), eventParams);
2740            var _fireEvent = function (tracking_id,name,params, event=null) {
2741                var eventData = {};
2742                var ContainerCodeHasTag = !options.gtm.gtm_just_data_layer && tracking_id.length > 0;
2743                if(ContainerCodeHasTag) {
2744                    params['send_to'] = tracking_id;
2745                }
2746                else if(!options.gtm.gtm_just_data_layer){
2747                    return
2748                }
2749
2750                if (params.hasOwnProperty('ecommerce')) {
2751                    eventData.ecommerce = params.ecommerce;
2752                    delete params.ecommerce;
2753                }
2754
2755                var automatedParams = { ...params };
2756                [params['manualName'], 'manualName', 'triggerType'].forEach(key => delete automatedParams[key]);
2757                if(event && (!event.hasOwnProperty('hasAutoParam') || (event.hasOwnProperty('hasAutoParam') && event.hasAutoParam))) {
2758                    eventData.automatedParameters = automatedParams;
2759                }
2760
2761// Move custom parameters to eventData
2762
2763                if (params.hasOwnProperty(params['manualName'])) {
2764                    eventData[params['manualName']] = params[params['manualName']];
2765                    delete params[params['manualName']];
2766                }
2767
2768                ['manualName','triggerType'].forEach(key => {
2769                    if (params.hasOwnProperty(key)) {
2770                        eventData[key] = params[key];
2771                        delete params[key];
2772                    }
2773                });
2774
2775                eventData.manualDataLayer = options.gtm.gtm_dataLayer_name ?? 'dataLayer';
2776
2777                eventData.event = name;
2778
2779                if (options.debug) {
2780                    if (ContainerCodeHasTag){
2781                        console.log('[Google GTM #' + tracking_id + '] ' + name, eventData);
2782                    }
2783                    else {
2784                        console.log('[Google GTM push to "'+datalayer_name+'"] ' + name, eventData);
2785                    }
2786                }
2787                window[datalayer_name].push(eventData);
2788
2789            };
2790
2791            var copyParams = Utils.copyProperties(eventParams, {}); // copy params because mapParamsToGTM can modify it
2792
2793            var params = mapParamsToGTM(ids,name,copyParams)
2794
2795            params.event_id = Utils.generateUniqueId(event);
2796
2797            _fireEvent(ids, name, params, event);
2798        }
2799
2800        function normalizeEventName(eventName) {
2801
2802            var matches = {
2803                ViewContent: 'view_item',
2804                AddToCart: 'add_to_cart',
2805                AddToWishList: 'add_to_wishlist',
2806                InitiateCheckout: 'begin_checkout',
2807                Purchase: 'purchase',
2808                Lead: 'generate_lead',
2809                CompleteRegistration: 'sign_up',
2810                AddPaymentInfo: 'set_checkout_option'
2811            };
2812
2813            return matches.hasOwnProperty(eventName) ? matches[eventName] : eventName;
2814
2815        }
2816
2817        function mapParamsToGTM(tag,name,param) {
2818            //GA4 automatically collects a number of parameters for all events
2819            var hasGTM = false;
2820
2821            // end
2822            if (Array.isArray(tag)) {
2823                hasGTM = tag.some(function (element) {
2824                    return isGTM(element);
2825                });
2826            } else if(isGTM(tag)) {
2827                // tag is a string and matches GTM
2828                hasGTM = true;
2829            }
2830            if(hasGTM) {
2831                delete param.event_category;
2832                delete param.event_label;
2833
2834                delete param.analytics_storage;
2835                delete param.ad_storage;
2836                delete param.ad_user_data;
2837                delete param.ad_personalization;
2838
2839                if(name === 'search') {
2840                    param['search'] = param.search_term;
2841                    delete param.search_term;
2842                    delete param.dynx_itemid;
2843                    delete param.dynx_pagetype;
2844                    delete param.dynx_totalvalue;
2845                }
2846            }
2847            return param;
2848        }
2849
2850        function isGTM(tag) {
2851            return tag.indexOf('GTM') === 0;
2852        }
2853        /**
2854         * Public API
2855         */
2856        return {
2857            tag: function() {
2858                return "gtm";
2859            },
2860            isEnabled: function () {
2861                return options.hasOwnProperty('gtm');
2862            },
2863            disable: function () {
2864                initialized = false;
2865            },
2866            updateEnhancedConversionData : function () {
2867                if (!initialized || !this.isEnabled()) {
2868                    return;
2869                }
2870                if(options.hasOwnProperty("tracking_analytics") && options.tracking_analytics.hasOwnProperty("userDataEnable") && options.tracking_analytics.userDataEnable) {
2871                    var advanced = Utils.getAdvancedFormData();
2872                    if (Object.keys(advanced).length > 0) {
2873                        window[datalayer_name].push({'user_data' : advanced});
2874                    }
2875                }
2876            },
2877            loadPixel: function () {
2878
2879                if (initialized || !this.isEnabled() || !Utils.consentGiven('analytics')) {
2880                    return;
2881                }
2882                datalayer_name = options.gtm.gtm_dataLayer_name ?? 'dataLayer';
2883
2884                for (var i = 0; i < options.gtm.trackingIds.length; i++) {
2885                    var trackingId = options.gtm.trackingIds[i];
2886                    if (!options.gtm.gtm_just_data_layer) {
2887                        console.log('[PYS] Google Tag Manager container code loaded');
2888                        Utils.loadGTMScript(trackingId);
2889                        break;
2890                    }
2891                }
2892                if(options.gtm.gtm_just_data_layer) {
2893                    console.warn && console.warn("[PYS] Google Tag Manager container code placement set to OFF !!!");
2894                    console.warn && console.warn("[PYS] Data layer codes are active but GTM container must be loaded using custom coding !!!");
2895                    if(options.gtm.trackingIds.length == 0){
2896                        Utils.loadGTMScript();
2897                    }
2898                }
2899
2900                if(options.hasOwnProperty("tracking_analytics") && options.tracking_analytics.hasOwnProperty("userDataEnable") && options.tracking_analytics.userDataEnable){
2901                    var advanced = Utils.getAdvancedFormData();
2902                    if(Object.keys(advanced).length > 0){
2903                        window[datalayer_name].push({'user_data' : advanced});
2904                    }
2905                }
2906
2907
2908                var config = {};
2909
2910                if(options.user_id && options.user_id != 0) {
2911                    config.user_id = options.user_id;
2912                }
2913
2914                // Cross-Domain tracking
2915
2916                var ids = options.gtm.trackingIds;
2917
2918
2919                initialized = true;
2920
2921                Utils.fireStaticEvents('gtm');
2922            },
2923
2924            fireEvent: function (name, data) {
2925
2926                if (!initialized || !this.isEnabled()) {
2927                    return false;
2928                }
2929
2930                data.delay = data.delay || 0;
2931                data.params = data.params || {};
2932
2933                if (data.delay === 0) {
2934
2935                    fireEvent(name, data);
2936
2937                } else {
2938
2939                    setTimeout(function (name, params) {
2940                        fireEvent(name, params);
2941                    }, data.delay * 1000, name, data);
2942
2943                }
2944
2945                return true;
2946
2947            },
2948
2949            onCommentEvent: function (event) {
2950                this.fireEvent(event.name, event);
2951            },
2952
2953            onDownloadEvent: function (event) {
2954                this.fireEvent(event.name, event);
2955            },
2956
2957            onFormEvent: function (event) {
2958                this.fireEvent(event.name, event);
2959            },
2960
2961            onWooAddToCartOnButtonEvent: function (product_id, prod_info = null) {
2962                if(!options.dynamicEvents.woo_add_to_cart_on_button_click.hasOwnProperty(this.tag()))
2963                    return;
2964                var event = Utils.clone(options.dynamicEvents.woo_add_to_cart_on_button_click[this.tag()]);
2965
2966                if (window.pysWooProductData.hasOwnProperty(product_id)) {
2967                    if (window.pysWooProductData[product_id].hasOwnProperty('gtm')) {
2968                        Utils.copyProperties(window.pysWooProductData[product_id]['gtm'].params, event.params)
2969                        this.fireEvent(event.name, event);
2970                    }
2971                }
2972
2973            },
2974
2975            onWooAddToCartOnSingleEvent: function (product_id, qty, product_type, is_external, $form, prod_info) {
2976                window.pysWooProductData = window.pysWooProductData || [];
2977
2978                if(!options.dynamicEvents.woo_add_to_cart_on_button_click.hasOwnProperty(this.tag()))
2979                    return;
2980                var event = Utils.clone(options.dynamicEvents.woo_add_to_cart_on_button_click[this.tag()]);
2981
2982                if (product_type === Utils.PRODUCT_VARIABLE && !options.gtm.wooVariableAsSimple) {
2983                    product_id = parseInt($form.find('input[name="variation_id"]').val());
2984                }
2985
2986                if (window.pysWooProductData.hasOwnProperty(product_id)) {
2987                    if (window.pysWooProductData[product_id].hasOwnProperty('gtm')) {
2988
2989                        Utils.copyProperties(window.pysWooProductData[product_id]['gtm'].params, event.params);
2990
2991                        params = event.params.hasOwnProperty('ecommerce') ? event.params.ecommerce : event.params;
2992
2993                        if(product_type === Utils.PRODUCT_GROUPED ) {
2994                            var groupValue = 0;
2995                            $form.find(".woocommerce-grouped-product-list .qty").each(function(index){
2996                                var childId = $(this).attr('name').replaceAll("quantity[","").replaceAll("]","");
2997                                var quantity = parseInt($(this).val());
2998                                if(isNaN(quantity)) {
2999                                    quantity = 0;
3000                                }
3001                                var childItem = window.pysWooProductData[product_id]['gtm'].grouped[childId];
3002                                params.items.forEach(function(el,index,array) {
3003                                    if(el.id == childItem.content_id) {
3004                                        if(quantity > 0){
3005                                            el.quantity = quantity;
3006                                            el.price = childItem.price;
3007                                        } else {
3008                                            array.splice(index, 1);
3009                                        }
3010                                    }
3011                                });
3012                                groupValue += childItem.price * quantity;
3013                            });
3014
3015                            if(options.woo.addToCartOnButtonValueEnabled &&
3016                                options.woo.addToCartOnButtonValueOption !== 'global' &&
3017                                params.hasOwnProperty('value')) {
3018                                params.value = groupValue;
3019                            }
3020
3021                            if(groupValue == 0) return; // skip if no items selected
3022                        } else {
3023                            // update items qty param
3024                            params.items[0].quantity = qty;
3025                        }
3026
3027                        // maybe customize value option
3028                        if (options.woo.addToCartOnButtonValueEnabled &&
3029                            options.woo.addToCartOnButtonValueOption !== 'global' &&
3030                            product_type !== Utils.PRODUCT_GROUPED)
3031                        {
3032                            if(params.hasOwnProperty('value')) {
3033                                params.value = params.items[0].price * qty;
3034                            }
3035
3036                        }
3037
3038
3039                        this.fireEvent(event.name, event);
3040                    }
3041                }
3042
3043            },
3044
3045            onWooRemoveFromCartEvent: function (event) {
3046
3047                this.fireEvent(event.name, event);
3048
3049            },
3050
3051            onEddAddToCartOnButtonEvent: function (download_id, price_index, qty) {
3052                if(!options.dynamicEvents.edd_add_to_cart_on_button_click.hasOwnProperty(this.tag()))
3053                    return;
3054                var event = Utils.clone(options.dynamicEvents.edd_add_to_cart_on_button_click[this.tag()]);
3055
3056
3057                if (window.pysEddProductData.hasOwnProperty(download_id)) {
3058
3059                    var index;
3060
3061                    if (price_index) {
3062                        index = download_id + '_' + price_index;
3063                    } else {
3064                        index = download_id;
3065                    }
3066
3067                    if (window.pysEddProductData[download_id].hasOwnProperty(index)) {
3068                        if (window.pysEddProductData[download_id][index].hasOwnProperty('gtm')) {
3069
3070                            Utils.copyProperties(window.pysEddProductData[download_id][index]['gtm'].params, event.params);
3071                            item = event.params.hasOwnProperty('ecommerce') ? event.params.ecommerce.items[0] : event.params.items[0];
3072                            // update items qty param
3073                            item.quantity = qty;
3074
3075                            this.fireEvent(event.name,event);
3076
3077                        }
3078                    }
3079
3080                }
3081
3082            },
3083
3084            onEddRemoveFromCartEvent: function (event) {
3085                this.fireEvent(event.name, event);
3086            },
3087            onPageScroll: function (event) {
3088                this.fireEvent(event.name, event);
3089            },
3090            onTime: function (event) {
3091                this.fireEvent(event.name, event);
3092            },
3093        };
3094
3095    }(options);
3096
3097    var getPixelBySlag = function getPixelBySlag(slug) {
3098        switch (slug) {
3099            case "facebook": return window.pys.Facebook;
3100            case "ga": return window.pys.Analytics;
3101            case "gtm": return window.pys.GTM;
3102            case "bing": return window.pys.Bing;
3103            case "pinterest": return window.pys.Pinterest;
3104	        case "reddit": return window.pys.Reddit;
3105        }
3106    }
3107
3108    window.pys = window.pys || {};
3109    window.pys.Facebook = Facebook;
3110    window.pys.Analytics = Analytics;
3111    window.pys.GTM = GTM;
3112    window.pys.Utils = Utils;
3113    window.pys.getPixelBySlag = getPixelBySlag;
3114
3115    // Export getPixelBySlag globally for backward compatibility
3116    window.getPixelBySlag = getPixelBySlag;
3117
3118
3119    $(document).ready(function () {
3120
3121        if($("#pys_late_event").length > 0) {
3122            var dirAttr = $("#pys_late_event").attr("dir");
3123            if (dirAttr) {
3124                try {
3125                    var events = JSON.parse(dirAttr);
3126                } catch (e) {
3127                    console.warn("Invalid JSON in pys_late_event dir attribute:", e);
3128                }
3129            } else {
3130                console.warn("pys_late_event dir attribute is undefined or empty");
3131            }
3132            if (events) {
3133                for (var key in events) {
3134                    var event = {};
3135                    event[events[key].e_id] = [events[key]];
3136                    if (options.staticEvents.hasOwnProperty(key)) {
3137                        Object.assign(options.staticEvents[key], event);
3138                    } else {
3139                        options.staticEvents[key] = event;
3140                    }
3141                }
3142            }
3143        }
3144
3145        var Pinterest = Utils.setupPinterestObject();
3146        var Bing = Utils.setupBingObject();
3147	    var Reddit = Utils.setupRedditObject();
3148
3149        if(options.hasOwnProperty('cookie'))
3150        {
3151            if(options.cookie.externalID_disabled_by_api || options.cookie.disabled_all_cookie)
3152            {
3153                Cookies.remove('pbid')
3154            }
3155            if(options.cookie.disabled_advanced_form_data_cookie || options.cookie.disabled_all_cookie)
3156            {
3157                Cookies.remove('pys_advanced_form_data')
3158            }
3159            if(options.cookie.disabled_landing_page_cookie || options.cookie.disabled_all_cookie)
3160            {
3161                Cookies.remove('pys_landing_page')
3162                Cookies.remove('last_pys_landing_page')
3163            }
3164            if(options.cookie.disabled_trafficsource_cookie || options.cookie.disabled_all_cookie)
3165            {
3166                Cookies.remove('pysTrafficSource')
3167                Cookies.remove('last_pysTrafficSource')
3168            }
3169            if(options.cookie.disabled_first_visit_cookie || options.cookie.disabled_all_cookie)
3170            {
3171                Cookies.remove('pys_first_visit')
3172
3173            }
3174            if(options.cookie.disabled_utmTerms_cookie || options.cookie.disabled_all_cookie)
3175            {
3176                $.each(Utils.utmTerms, function (index, name) {
3177                    Cookies.remove('pys_' + name)
3178                });
3179                $.each(Utils.utmTerms, function (index, name) {
3180                    Cookies.remove('last_pys_' + name)
3181                });
3182            }
3183            if(options.cookie.disabled_utmId_cookie || options.cookie.disabled_all_cookie)
3184            {
3185                $.each(Utils.utmId,function(index,name) {
3186                    Cookies.remove('pys_' + name)
3187                })
3188                $.each(Utils.utmId,function(index,name) {
3189                    Cookies.remove('last_pys_' + name)
3190                });
3191            }
3192        }
3193
3194
3195        if (options.gdpr.cookie_law_info_integration_enabled) {
3196            var cli_cookie = Cookies.get('cookieyes-consent') ?? Cookies.get('viewed_cookie_policy');
3197
3198            if (typeof cli_cookie !== 'undefined') {
3199                if (cli_cookie === Cookies.get('cookieyes-consent') && getCookieYes('analytics') == 'yes') {
3200                    Utils.manageCookies();
3201                } else if (cli_cookie === Cookies.get('viewed_cookie_policy') && cli_cookie == 'yes') {
3202                    Utils.manageCookies();
3203                }
3204            }
3205        }
3206
3207        if ( options.gdpr.consent_magic_integration_enabled && typeof CS_Data !== "undefined" ) {
3208            if ( CS_Data.cs_script_cat.pys == CS_Data.cs_necessary_cat_id || CS_Data.cs_script_cat.pys == 0 ) {
3209                Utils.manageCookies();
3210            } else if ( Cookies.get( 'cs_enabled_cookie_term' + CS_Data.test_prefix + '_' + CS_Data.cs_script_cat.pys ) == 'yes' ) {
3211                Utils.manageCookies();
3212            }
3213        } else {
3214            Utils.manageCookies();
3215        }
3216
3217        Utils.setupGdprCallbacks();
3218        // page scroll event
3219        if ( options.dynamicEvents.hasOwnProperty("automatic_event_scroll")
3220        ) {
3221
3222            var singlePageScroll = function () {
3223
3224
3225                var docHeight = $(document).height() - $(window).height();
3226                var isFired = false;
3227
3228                if (options.dynamicEvents.hasOwnProperty("automatic_event_scroll")) {
3229                    var pixels = Object.keys(options.dynamicEvents.automatic_event_scroll);
3230                    for(var i = 0;i<pixels.length;i++) {
3231                        var event = Utils.clone(options.dynamicEvents.automatic_event_scroll[pixels[i]]);
3232                        var scroll = Math.round(docHeight * event.scroll_percent / 100)// convert % to absolute positions
3233
3234                        if(scroll < $(window).scrollTop()) {
3235	                        if ( pixels[i] !== 'reddit') {
3236		                        Utils.copyProperties( Utils.getRequestParams(), event.params );
3237	                        }
3238	                        getPixelBySlag( pixels[ i ] ).onPageScroll( event );
3239                            isFired = true
3240                        }
3241                    }
3242                }
3243                if(isFired) {
3244                    $(document).off("scroll",singlePageScroll);
3245                }
3246            }
3247            $(document).on("scroll",singlePageScroll);
3248        }
3249
3250
3251        if (options.dynamicEvents.hasOwnProperty("automatic_event_time_on_page")) {
3252            var pixels = Object.keys(options.dynamicEvents.automatic_event_time_on_page);
3253            var time = options.dynamicEvents.automatic_event_time_on_page[pixels[0]].time_on_page; // the same for all pixel
3254            setTimeout(function(){
3255                for(var i = 0;i<pixels.length;i++) {
3256                    var event = Utils.clone(options.dynamicEvents.automatic_event_time_on_page[pixels[i]]);
3257
3258	                if ( pixels[i] !== 'reddit') {
3259		                Utils.copyProperties(Utils.getRequestParams(), event.params);
3260	                }
3261                    getPixelBySlag(pixels[i]).onTime(event);
3262                }
3263            },time*1000);
3264        }
3265
3266        // setup Click Event
3267        if (options.dynamicEvents.hasOwnProperty("automatic_event_download")) {
3268
3269            $(document).onFirst('click', 'a, button, input[type="button"], input[type="submit"]', function (e) {
3270
3271                var $elem = $(this);
3272
3273                // Download
3274                if(options.dynamicEvents.hasOwnProperty("automatic_event_download")
3275                ) {
3276                    var isFired = false;
3277                    if ($elem.is('a')) {
3278                        var href = $elem.attr('href');
3279                        if (typeof href !== "string") {
3280                            return;
3281                        }
3282                        href = href.trim();
3283                        var extension = Utils.getLinkExtension(href);
3284                        var track_download = false;
3285
3286                        if (extension.length > 0) {
3287
3288                            if(options.dynamicEvents.hasOwnProperty("automatic_event_download") ) {
3289                                var pixels = Object.keys(options.dynamicEvents.automatic_event_download);
3290                                for (var i = 0; i < pixels.length; i++) {
3291                                    var event = Utils.clone(options.dynamicEvents.automatic_event_download[pixels[i]]);
3292                                    var extensions = event.extensions;
3293                                    if (extensions.includes(extension)) {
3294
3295                                        if( pixels[i] == "tiktok" || pixels[i] == "reddit" ) {
3296                                            getPixelBySlag(pixels[i]).fireEvent(tikEvent.name, event);
3297                                        } else {
3298                                            if (options.enable_remove_download_url_param) {
3299                                                href = href.split('?')[0];
3300                                            }
3301                                            event.params.download_url = href;
3302                                            event.params.download_type = extension;
3303                                            event.params.download_name = Utils.getLinkFilename(href);
3304                                            getPixelBySlag(pixels[i]).onDownloadEvent(event);
3305                                        }
3306
3307                                        isFired = true;
3308                                    }
3309                                }
3310                            }
3311                        }
3312                    }
3313                    if(isFired) { // prevent duplicate events on the same element
3314                        return;
3315                    }
3316                }
3317            });
3318        }
3319
3320
3321        // setup Dynamic events
3322        $.each(options.triggerEventTypes, function (triggerType, events) {
3323
3324            $.each(events, function (eventId, triggers) {
3325
3326                switch (triggerType) {
3327                    case 'url_click':
3328                        //@see: Utils.setupURLClickEvents()
3329                        break;
3330
3331                    case 'css_click':
3332                        Utils.setupCSSClickEvents(eventId, triggers);
3333                        break;
3334
3335                    case 'css_mouseover':
3336                        Utils.setupMouseOverClickEvents(eventId, triggers);
3337                        break;
3338
3339                    case 'scroll_pos':
3340                        Utils.setupScrollPosEvents(eventId, triggers);
3341                        break;
3342                    case 'comment':
3343                        Utils.setupCommentEvents(eventId, triggers);
3344                        break;
3345                }
3346
3347            });
3348
3349        });
3350        // setup WooCommerce events
3351        if (options.woo.enabled) {
3352
3353            // WooCommerce AddToCart
3354            if (options.dynamicEvents.hasOwnProperty("woo_add_to_cart_on_button_click")
3355                && options.woo.hasOwnProperty("addToCartCatchMethod")
3356                && options.woo.addToCartCatchMethod === "add_cart_js"
3357            ) {
3358
3359                // Loop, any kind of "simple" product, except external
3360                $('.add_to_cart_button:not(.product_type_variable,.product_type_bundle,.single_add_to_cart_button)').on("click",function (e) {
3361
3362                    var product_id = $(this).data('product_id');
3363                    if (typeof product_id !== 'undefined') {
3364                        if (options.dynamicEvents.hasOwnProperty("woo_add_to_cart_on_button_click")) {
3365                            var tmpEventID = pys_generate_token();
3366                            $.each(options.dynamicEvents.woo_add_to_cart_on_button_click, function (i, tag) {
3367                                tag.eventID = tmpEventID;
3368                            });
3369                        }
3370                        if (typeof product_id !== 'undefined') {
3371                            Facebook.onWooAddToCartOnButtonEvent(product_id);
3372                            Analytics.onWooAddToCartOnButtonEvent(product_id);
3373                            GTM.onWooAddToCartOnButtonEvent(product_id);
3374                            Pinterest.onWooAddToCartOnButtonEvent(product_id);
3375                            Bing.onWooAddToCartOnButtonEvent(product_id);
3376	                        Reddit.onWooAddToCartOnButtonEvent(product_id);
3377                        }
3378                    }
3379                });
3380
3381                // Single Product
3382                // tap try to https://stackoverflow.com/questions/30990967/on-tap-click-event-firing-twice-how-to-avoid-it
3383                //  $(document) not work
3384                $('body').onFirst('click','button.single_add_to_cart_button,.single_add_to_cart_button',function (e) {
3385
3386                    var $button = $(this);
3387
3388                    if ($button.hasClass('disabled')) {
3389                        return;
3390                    }
3391
3392                    var $form = $button.closest('form');
3393
3394                    var product_type = Utils.PRODUCT_SIMPLE;
3395
3396                    if ($form.length === 0) {
3397                        return ;
3398                    } else if ($form.hasClass('variations_form')) {
3399                        product_type = Utils.PRODUCT_VARIABLE;
3400                    } else if($form.hasClass('bundle_form')) {
3401                        product_type = Utils.PRODUCT_BUNDLE;
3402                    } else if($form.hasClass('grouped_form')) {
3403                        product_type = Utils.PRODUCT_GROUPED;
3404                    }
3405
3406
3407
3408
3409                    var product_id;
3410                    var qty;
3411
3412                    if (product_type === Utils.PRODUCT_GROUPED) {
3413                        qty = 1;
3414                        product_id = parseInt($form.find('*[name="add-to-cart"]').val());
3415                    } else if (product_type === Utils.PRODUCT_VARIABLE) {
3416                        product_id = parseInt($form.find('*[name="add-to-cart"]').val());
3417                        var qtyTag = $form.find('input[name="quantity"]');
3418                        if(qtyTag.length <= 0) {
3419                            qtyTag = $form.find('select[name="quantity"]');
3420                        }
3421                        qty = parseInt(qtyTag.val());
3422                    } else {
3423                        product_id = parseInt($form.find('*[name="add-to-cart"]').val());
3424                        var qtyTag = $form.find('input[name="quantity"]');
3425                        if(qtyTag.length <= 0) {
3426                            qtyTag = $form.find('select[name="quantity"]');
3427                        }
3428                        qty = parseInt(qtyTag.val());
3429                    }
3430
3431                    if(options.dynamicEvents.hasOwnProperty("woo_add_to_cart_on_button_click")){
3432                        var tmpEventID = pys_generate_token();
3433                        $.each(options.dynamicEvents.woo_add_to_cart_on_button_click, function (i, tag) {
3434                            tag.eventID = tmpEventID;
3435                        });
3436                    }
3437
3438                    Facebook.onWooAddToCartOnSingleEvent(product_id, qty, product_type, $form);
3439                    Analytics.onWooAddToCartOnSingleEvent(product_id, qty, product_type, $form);
3440
3441                    GTM.onWooAddToCartOnSingleEvent(product_id, qty, product_type, $form);
3442
3443                    Pinterest.onWooAddToCartOnSingleEvent(product_id, qty, product_type, false, $form);
3444                    Bing.onWooAddToCartOnSingleEvent(product_id, qty, product_type, false, $form);
3445	                Reddit.onWooAddToCartOnSingleEvent(product_id, qty, product_type, false, $form);
3446
3447                });
3448
3449            }
3450
3451            // WooCommerce RemoveFromCart
3452            if (options.dynamicEvents.hasOwnProperty("woo_remove_from_cart")) {
3453
3454                $('body').on('click', options.woo.removeFromCartSelector, function (e) {
3455
3456                    var $a = $(e.currentTarget),
3457                        href = $a.attr('href');
3458
3459                    // extract cart item hash from remove button URL
3460                    var regex = new RegExp("[\\?&]remove_item=([^&#]*)"),
3461                        results = regex.exec(href);
3462
3463                    if (results !== null) {
3464
3465                        var item_hash = results[1];
3466
3467                        if (options.dynamicEvents["woo_remove_from_cart"].hasOwnProperty(item_hash)) {
3468                            var events = options.dynamicEvents["woo_remove_from_cart"][item_hash];
3469                            Utils.fireEventForAllPixel("onWooRemoveFromCartEvent",events)
3470                        }
3471
3472                    }
3473
3474                });
3475            }
3476        }
3477
3478        // setup EDD events
3479        if (options.edd.enabled) {
3480
3481            // EDD AddToCart
3482            if (options.dynamicEvents.hasOwnProperty("edd_add_to_cart_on_button_click")) {
3483
3484                $('form.edd_download_purchase_form .edd-add-to-cart').on("click",function (e) {
3485
3486                    var $button = $(this);
3487                    var $form = $button.closest('form');
3488                    var variable_price = $button.data('variablePrice'); // yes/no
3489                    var price_mode = $button.data('priceMode'); // single/multi
3490                    var ids = [];
3491                    var quantities = [];
3492                    var qty;
3493                    var id;
3494
3495                    if (variable_price === 'yes' && price_mode === 'multi') {
3496
3497                        id = $form.find('input[name="download_id"]').val();
3498
3499                        // get selected variants
3500                        $.each($form.find('input[name="edd_options[price_id][]"]:checked'), function (i, el) {
3501                            ids.push(id + '_' + $(el).val());
3502                        });
3503
3504                        // get qty for selected variants
3505                        $.each(ids, function (i, variant_id) {
3506
3507                            var variant_index = variant_id.split('_', 2);
3508                            qty = $form.find('input[name="edd_download_quantity_' + variant_index[1] + '"]').val();
3509
3510                            if (typeof qty !== 'undefined') {
3511                                quantities.push(qty);
3512                            } else {
3513                                quantities.push(1);
3514                            }
3515
3516                        });
3517
3518                    } else if (variable_price === 'yes' && price_mode === 'single') {
3519
3520                        id = $form.find('input[name="download_id"]').val();
3521                        ids.push(id + '_' + $form.find('input[name="edd_options[price_id][]"]:checked').val());
3522
3523                        qty = $form.find('input[name="edd_download_quantity"]').val();
3524
3525                        if (typeof qty !== 'undefined') {
3526                            quantities.push(qty);
3527                        } else {
3528                            quantities.push(1);
3529                        }
3530
3531                    } else {
3532
3533                        ids.push($button.data('downloadId'));
3534
3535                        qty = $form.find('input[name="edd_download_quantity"]').val();
3536
3537                        if (typeof qty !== 'undefined') {
3538                            quantities.push(qty);
3539                        } else {
3540                            quantities.push(1);
3541                        }
3542                    }
3543
3544                    // fire event for each download/variant
3545                    $.each(ids, function (i, download_id) {
3546
3547                        var q = parseInt(quantities[i]);
3548                        var variant_index = download_id.toString().split('_', 2);
3549                        var price_index;
3550
3551                        if (variant_index.length === 2) {
3552                            download_id = variant_index[0];
3553                            price_index = variant_index[1];
3554                        }
3555
3556                        Facebook.onEddAddToCartOnButtonEvent(download_id, price_index, q);
3557                        Analytics.onEddAddToCartOnButtonEvent(download_id, price_index, q);
3558                        GTM.onEddAddToCartOnButtonEvent(download_id, price_index, q);
3559                        Pinterest.onEddAddToCartOnButtonEvent(download_id, price_index, q);
3560                        Bing.onEddAddToCartOnButtonEvent(download_id, price_index, q);
3561	                    Reddit.onEddAddToCartOnButtonEvent(download_id, price_index, q);
3562                    });
3563
3564                });
3565
3566            }
3567
3568
3569            // EDD RemoveFromCart
3570            if (options.dynamicEvents.hasOwnProperty("edd_remove_from_cart") ) {
3571
3572                $('form#edd_checkout_cart_form .edd_cart_remove_item_btn').on("click",function (e) {
3573
3574                    var href = $(this).attr('href');
3575                    if(href) {
3576                        var key = href.substring(href.indexOf('=') + 1).charAt(0);
3577                        if (options.dynamicEvents.edd_remove_from_cart.hasOwnProperty(key)) {
3578                            var events = options.dynamicEvents.edd_remove_from_cart[key];
3579                            Utils.fireEventForAllPixel("onEddRemoveFromCartEvent",events)
3580                        }
3581                    }
3582                });
3583
3584            }
3585
3586        }
3587
3588        // setup Comment Event
3589        if (options.dynamicEvents.hasOwnProperty("automatic_event_c
3589omment")
3590        ) {
3591
3592            $('form.comment-form').on("submit",function () {
3593                if (options.dynamicEvents.hasOwnProperty("automatic_event_comment")) {
3594                    var pixels = Object.keys(options.dynamicEvents.automatic_event_comment);
3595                    for (var i = 0; i < pixels.length; i++) {
3596	                    var event = Utils.clone(options.dynamicEvents.automatic_event_comment[pixels[i]]);
3597	                    if ( pixels[i] !== 'reddit') {
3598		                    Utils.copyProperties(Utils.getRequestParams(), event.params);
3599	                    }
3600                        getPixelBySlag(pixels[i]).onCommentEvent(event);
3601                    }
3602                }
3603            });
3604
3605        }
3606
3607
3608        // setup Form Event
3609        if ( options.dynamicEvents.hasOwnProperty("automatic_event_form")) {
3610
3611            $(document).onFirst('submit', 'form', function (e) {
3612
3613                var $form = $(this);
3614
3615                // exclude WP forms
3616                if ($form.hasClass('comment-form') || $form.hasClass('search-form') || $form.attr('id') === 'adminbarsearch') {
3617                    return;
3618                }
3619
3620                // exclude Woo forms
3621                if ($form.hasClass('woocommerce-product-search') || $form.hasClass('cart') || $form.hasClass('woocommerce-cart-form') ||
3622                    $form.hasClass('woocommerce-shipping-calculator') || $form.hasClass('checkout') || $form.hasClass('checkout_coupon')) {
3623                    return;
3624                }
3625
3626                // exclude EDD forms
3627                if ($form.hasClass('edd_form') || $form.hasClass('edd_download_purchase_form')) {
3628                    return;
3629                }
3630// exclude CF7 forms
3631                if ($form.hasClass('wpcf7-form')) {
3632                    return;
3633                }
3634                // exclude Forminator forms
3635                if ($form.hasClass('forminator-custom-form') || $form.hasClass('forminator_ajax')) {
3636                    return;
3637                }
3638                // exclude WPforms forms
3639                if ($form.hasClass('wpforms-form') || $form.hasClass('wpforms-ajax-form')) {
3640                    return;
3641                }
3642                // exclude Formidable forms
3643                /*if ($form.hasClass('frm-show-form')) {
3644                    return;
3645                }*/
3646                // exclude Ninja Forms forms
3647                if ($form.parent().hasClass('nf-form-layout')) {
3648                    return;
3649                }
3650                // exclude Fluent forms
3651                if ($form.hasClass('frm-fluent-form')) {
3652                    return;
3653                }
3654                if(!options.enable_success_send_form) {
3655                    var params = {
3656                        form_id: $form.attr('id'),
3657                        form_class: $form.attr('class'),
3658                        text: $form.find('[type="submit"]').is('input') ?
3659                            $form.find('[type="submit"]').val() : $form.find('[type="submit"]').text()
3660                    };
3661
3662                    if (options.dynamicEvents.hasOwnProperty("automatic_event_form")) {
3663                        var pixels = Object.keys(options.dynamicEvents.automatic_event_form);
3664                        for (var i = 0; i < pixels.length; i++) {
3665                            var event = Utils.clone(options.dynamicEvents.automatic_event_form[pixels[i]]);
3666
3667	                        if (pixels[i] === "tiktok" || pixels[i] === "reddit") {
3668                                getPixelBySlag(pixels[i]).fireEvent(event.name, event);
3669                            } else {
3670                                Utils.copyProperties(params, event.params,)
3671                                Utils.copyProperties(Utils.getRequestParam
3671s(), event.params);
3672                                getPixelBySlag(pixels[i]).onFormEvent(event);
3673                            }
3674                        }
3675                    }
3676                }
3677            });
3678
3679            document.addEventListener( 'wpcf7mailsent', function( event ) {
3680                var form_id = event.detail.contactFormId;
3681                sendFormAction($(event.target), form_id);
3682            }, false );
3683            //Forminator
3684            $(document).on( 'forminator:form:submit:success', function( event ){
3685                var form_id = $(event.target).find('input[name="form_id"]').val();
3686                sendFormAction($(event.target), form_id);
3687            });
3688
3689            //WPForm
3690            $('form.wpforms-form').on('wpformsAjaxSubmitSuccess', (event) => {
3691                var form_id = $(event.target).attr('data-formid');
3692                sendFormAction($(event.target), form_id);
3693            })
3694            $(document).on( 'frmFormComplete', function( event, form, response ) {
3695                const form_id = $(form).find('input[name="form_id"]').val();
3696                sendFormAction($(event.target), form_id);
3697            });
3698            // Ninja Forms
3699            $(document).onFirst('nfFormSubmitResponse', function (event, data) {
3700                const form_id = data.response.data.form_id;
3701                sendFormAction($(event.target), form_id);
3702            });
3703
3704            var fluentForms = $('form.frm-fluent-form');
3705            fluentForms.each(function() {
3706                var $form = $(this);
3707                $form.on('fluentform_submission_success', function(event) {
3708                    var $formItem = $(this);
3709                    var form_id = $formItem.attr('data-form_id');
3710                    sendFormAction($(event.target), form_id);
3711                });
3712            });
3713
3714        }
3715
3716
3717        // load pixel APIs
3718        Utils.loadPixels();
3719        // setup Enrich content
3720        if(Utils.isCheckoutPage()) {
3721            Utils.addCheckoutFields();
3722        }
3723    });
3724
3725    var sendFormAction = function (form_target, formId){
3726        var params = {
3727            form_id: formId,
3728            text: form_target.find('[type="submit"]').is('input') ? form_target.find('[type="submit"]').val() :
3729                form_target.find('.forminator-button-submit').text() != '' ? form_target.find('.forminator-button-submit').text() :
3730                    form_target.find('[type="submit"]').text()
3731        };
3732
3733        if (options.dynamicEvents.hasOwnProperty("automatic_event_form")) {
3734            var pixels = Object.keys(options.dynamicEvents.automatic_event_form);
3735            for (var i = 0; i < pixels.length; i++) {
3736                var event = options.dynamicEvents.automatic_event_form[pixels[i]];
3737                if (pixels[i] === "tiktok" || pixels[i] === "reddit") {
3738                    getPixelBySlag(pixels[i]).fireEvent(event.name, event);
3739                } else {
3740                    Utils.copyProperties(params, event.params)
3741                    Utils.copyProperties(Utils.getRequestParams(), event.params);
3742                    getPixelBySlag(pixels[i]).onFormEvent(event);
3743                }
3744            }
3745        }
3746    }
3747
3748}(jQuery, pysOptions);
3749
3750function pys_generate_token() {
3751    return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
3752        (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
3753    );
3754}
3755
3756function getBundlePriceOnSingleProduct(data) {
3757    var items_sum = 0;
3758    jQuery(".bundle_form .bundled_product").each(function(index){
3759        var id = jQuery(this).find(".cart").data("bundled_item_id");
3760        var item_price = data.prices[id];
3761        var item_quantity = jQuery(this).find(".bundled_qty").val();
3762        if(!jQuery(this).hasClass("bundled_item_optional") ||
3763            jQuery(this).find(".bundled_product_optional_checkbox input").prop('checked')) {
3764            items_sum += item_price*item_quantity;
3765        }
3766    });
3767    return items_sum;
3768}
3769function getUrlParameter(sParam) {
3770    var sPageURL = window.location.search.substring(1),
3771        sURLVariables = sPageURL.split('&'),
3772        sParameterName,
3773        i;
3774
3775    for (i = 0; i < sURLVariables.length; i++) {
3776        sParameterName = sURLVariables[i].split('=');
3777
3778        if (sParameterName[0] === sParam) {
3779            return sParameterName[1] === undefined ? true : decodeURIComponent(sParameterName[1]);
3780        }
3781    }
3782    return false;
3783};
3784function getCookieYes(key) {
3785    const cookiesObj = document.cookie
3786        .split(";")
3787        .reduce((ac, cv) => {
3788            const [k, v] = cv.split("=");
3789            if (k && v) ac[k.trim()] = v;
3790            return ac;
3791        }, {});
3792    const consentCookie = cookiesObj["cookieyes-consent"] || cookiesObj["wt_consent"];
3793    if (!consentCookie) return undefined;
3794    const { [key]: value } = consentCookie
3795        .split(",")
3796        .reduce((obj, pair) => {
3797            const [k, v] = pair.split(":");
3798            if (k && v) obj[k] = v;
3799            return obj;
3800        }, {});
3801    return value;
3802}
3803function getRootDomain(useSubdomain = false) {
3804    const hostname = window.location.hostname; // Get the current hostname
3805    // Check if tldjs is defined before using it
3806    if (typeof tldjs === "undefined") {
3807        console.warn("tldjs is not defined");
3808        return hostname; // Return hostname as a fallback
3809    }
3810
3811    const rootDomain = tldjs.getDomain(hostname); // Use tldjs to extract the root domain
3812
3813    // Return the root domain with or without a leading dot based on useSubdomain
3814    return rootDomain ? (useSubdomain ? '.' + rootDomain : rootDomain) : hostname;
3815}

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.