PageSourceSearch

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

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

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.