PageSourceSearch

https://www.crownasia.com.ph/wp-content/plugins/pixelyoursite/dist/scripts/public.js?ver=11.2.0.3

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

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.