PageSourceSearch

https://www.fo-der.org/wp-content/plugins/pixelyoursite/dist/scripts/public.js?ver=9.3.7

js fo-der.org collected 2026-10-02 12:51:16 UTC 103,556 bytes, 2,673 lines download raw bytes

1/* global pysOptions */
2
3// https://bitbucket.org/pixelyoursite/pys_pro_7/issues/7/possible-ie-11-error
4// https://tc39.github.io/ecma262/#sec-array.prototype.includes
5if (!Array.prototype.includes) {
6    Object.defineProperty(Array.prototype, 'includes', {
7        value: function (searchElement, fromIndex) {
8
9            if (this == null) {
10                throw new TypeError('"this" is null or not defined');
11            }
12
13            // 1. Let O be ? ToObject(this value).
14            var o = Object(this);
15
16            // 2. Let len be ? ToLength(? Get(O, "length")).
17            var len = o.length >>> 0;
18
19            // 3. If len is 0, return false.
20            if (len === 0) {
21                return false;
22            }
23
24            // 4. Let n be ? ToInteger(fromIndex).
25            //    (If fromIndex is undefined, this step produces the value 0.)
26            var n = fromIndex | 0;
27
28            // 5. If n ≥ 0, then
29            //  a. Let k be n.
30            // 6. Else n < 0,
31            //  a. Let k be len + n.
32            //  b. If k < 0, let k be 0.
33            var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
34
35            function sameValueZero(x, y) {
36                return x === y || (typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y));
37            }
38
39            // 7. Repeat, while k < len
40            while (k < len) {
41                // a. Let elementK be the result of ? Get(O, ! ToString(k)).
42                // b. If SameValueZero(searchElement, elementK) is true, return true.
43                if (sameValueZero(o[k], searchElement)) {
44                    return true;
45                }
46                // c. Increase k by 1.
47                k++;
48            }
49
50            // 8. Return false
51            return false;
52        }
53    });
54}
55
56!function ($, options) {
57
58    if (options.debug) {
59        console.log('PYS:', options);
60    }
61
62    var dummyPinterest = function () {
63
64        /**
65         * Public API
66         */
67        return {
68
69            isEnabled: function () {
70            },
71
72            disable: function () {
73            },
74
75            loadPixel: function () {
76            },
77
78            fireEvent: function (name, data) {
79                return false;
80            },
81
82            onCommentEvent: function () {
83            },
84
85            onDownloadEvent: function (params) {
86            },
87
88            onFormEvent: function (params) {
89            },
90
91            onWooAddToCartOnButtonEvent: function (product_id) {
92            },
93
94            onWooAddToCartOnSingleEvent: function (product_id, qty, is_variable, is_external, $form) {
95            },
96
97            onWooRemoveFromCartEvent: function (cart_item_hash) {
98            },
99
100            onEddAddToCartOnButtonEvent: function (download_id, price_index, qty) {
101            },
102
103            onEddRemoveFromCartEvent: function (item) {
104            },
105            onPageScroll: function (event) {},
106            onTime: function (event) {
107
108            },
109
110        }
111
112    }();
113
114    var dummyBing = function () {
115
116        /**
117         * Public API
118         */
119        return {
120
121            isEnabled: function () {
122            },
123
124            disable: function () {
125            },
126
127            loadPixel: function () {
128            },
129
130            fireEvent: function (name, data) {
131                return false;
132            },
133
134            onAdSenseEvent: function () {
135            },
136
137            onClickEvent: function (params) {
138            },
139
140            onWatchVideo: function (params) {
141            },
142
143            onCommentEvent: function () {
144            },
145
146            onFormEvent: function (params) {
147            },
148
149            onDownloadEvent: function (params) {
150            },
151
152            onWooAddToCartOnButtonEvent: function (product_id) {
153            },
154
155            onWooAddToCartOnSingleEvent: function (product_id, qty, is_variable, is_external, $form) {
156            },
157
158            onWooRemoveFromCartEvent: function (cart_item_hash) {
159            },
160
161            onWooAffiliateEvent: function (product_id) {
162            },
163
164            onWooPayPalEvent: function () {
165            },
166
167            onEddAddToCartOnButtonEvent: function (download_id, price_index, qty) {
168            },
169
170            onEddRemoveFromCartEvent: function (item) {
171            },
172
173            onPageScroll: function (event) {
174            },
175
176            onTime: function (event) {
177            },
178
179        }
180
181    }();
182
183    var Utils = function (options) {
184
185        var Pinterest = dummyPinterest;
186
187        var Bing = dummyBing;
188
189        var gtag_loaded = false;
190
191        let isNewSession = checkSession();
192
193        var utmTerms = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content'];
194
195        var utmId = ['fbadid', 'gadid', 'padid', 'bingid'];
196
197        function validateEmail(email) {
198            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,}))$/;
199            return re.test(email);
200        }
201        function getDomain(url) {
202
203            url = url.replace(/(https?:\/\/)?(www.)?/i, '');
204
205            if (url.indexOf('/') !== -1) {
206                return url.split('/')[0];
207            }
208
209            return url;
210        }
211        function loadPixels() {
212
213            if (!options.gdpr.all_disabled_by_api) {
214
215                if (!options.gdpr.facebook_disabled_by_api) {
216                    Facebook.loadPixel();
217                }
218
219                if (!options.gdpr.analytics_disabled_by_api) {
220                    Analytics.loadPixel();
221                }
222
223                if (!options.gdpr.pinterest_disabled_by_api) {
224                    Pinterest.loadPixel();
225                }
226
227                if (!options.gdpr.bing_disabled_by_api) {
228                    Bing.loadPixel();
229                }
230            }
231            if (options.gdpr.consent_magic_integration_enabled && typeof CS_Data !== "undefined") {
232                if (typeof CS_Data.cs_google_analytics_consent_mode !== "undefined" && CS_Data.cs_google_analytics_consent_mode == 1) {
233                    Analytics.loadPixel();
234                }
235            }
236
237        }
238
239        function checkSession() {
240            let duration = options.last_visit_duration * 60000
241            if( Cookies.get('pys_start_session') === undefined ||
242                Cookies.get('pys_session_limit') === undefined) {
243                var now = new Date();
244                now.setTime(now.getTime() + duration);
245                Cookies.set('pys_session_limit', true,{ expires: now })
246                Cookies.set('pys_start_session', true)
247                return true
248            }
249            return false
250
251        }
252
253        function getTrafficSource() {
254
255            try {
256
257                let referrer = document.referrer.toString(),
258                    source;
259
260                let direct = referrer.length === 0;
261                let internal = direct ? false : referrer.indexOf(options.siteUrl) === 0;
262                let external = !direct && !internal;
263
264                if (external === false) {
265                    source = 'direct';
266                } else {
267                    source = referrer;
268                }
269
270                if (source !== 'direct') {
271                    // leave only domain (Issue #70)
272                    return getDomain(source);
273                } else {
274                    return source;
275                }
276
277            } catch (e) {
278                console.error(e);
279                return 'direct';
280            }
281
282        }
283
284        /**
285         * Return query variables object with where property name is query variable
286         * and property value is query variable value.
287         */
288        function getQueryVars() {
289
290            try {
291
292                var result = {},
293                    tmp = [];
294
295                window.location.search
296                    .substr(1)
297                    .split("&")
298                    .forEach(function (item) {
299
300                        tmp = item.split('=');
301
302                        if (tmp.length > 1) {
303                            result[tmp[0]] = tmp[1];
304                        }
305
306                    });
307
308                return result;
309
310            } catch (e) {
311                console.error(e);
312                return {};
313            }
314
315        }
316
317
318        function getUTMId(useLast = false) {
319            try {
320                let cookiePrefix = 'pys_'
321                let terms = [];
322                if (useLast) {
323                    cookiePrefix = 'last_pys_'
324                }
325                $.each(utmId, function (index, name) {
326                    if (Cookies.get(cookiePrefix + name)) {
327                        terms[name] = Cookies.get(cookiePrefix + name)
328                    }
329                });
330                return terms;
331            } catch (e) {
332                console.error(e);
333                return [];
334            }
335        }
336        /**
337         * Return UTM terms from request query variables or from cookies.
338         */
339        function getUTMs(useLast = false) {
340
341            try {
342                let cookiePrefix = 'pys_'
343                if(useLast) {
344                    cookiePrefix = 'last_pys_'
345                }
346                let terms = [];
347                $.each(utmTerms, function (index, name) {
348                    if (Cookies.get(cookiePrefix + name)) {
349                        let value = Cookies.get(cookiePrefix + name);
350                        terms[name] = filterEmails(value); // do not allow email in request params (Issue #70)
351                    }
352                });
353
354                return terms;
355
356            } catch (e) {
357                console.error(e);
358                return [];
359            }
360
361        }
362
363        function getDateTime() {
364            var dateTime = new Array();
365            var date = new Date(),
366                days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
367                months = ['January', 'February', 'March', 'April', 'May', 'June',
368                    'July', 'August', 'September', 'October', 'November', 'December'
369                ],
370                hours = ['00-01', '01-02', '02-03', '03-04', '04-05', '05-06', '06-07', '07-08',
371                    '08-09', '09-10', '10-11', '11-12', '12-13', '13-14', '14-15', '15-16', '16-17',
372                    '17-18', '18-19', '19-20', '20-21', '21-22', '22-23', '23-24'
373                ];
374            dateTime.push(hours[date.getHours()]);
375            dateTime.push(days[date.getDay()]);
376            dateTime.push(months[date.getMonth()]);
377            return dateTime;
378        }
379
380        function filterEmails(value) {
381            return validateEmail(value) ? undefined : value;
382        }
383
384        /**
385         * PUBLIC API
386         */
387        return {
388            PRODUCT_SIMPLE : 0,
389            PRODUCT_VARIABLE : 1,
390            PRODUCT_BUNDLE : 2,
391            PRODUCT_GROUPED : 3,
392
393            fireEventForAllPixel:function(functionName,events){
394                if (events.hasOwnProperty(Facebook.tag()))
395                    Facebook[functionName](events[Facebook.tag()]);
396                if (events.hasOwnProperty(Analytics.tag()))
397                    Analytics[functionName](events[Analytics.tag()]);
398                if (events.hasOwnProperty(Pinterest.tag()))
399                    Pinterest[functionName](events[Pinterest.tag()]);
400                if (events.hasOwnProperty(Bing.tag()))
401                    Bing[functionName](events[Bing.tag()]);
402            },
403
404            setupPinterestObject: function () {
405                Pinterest = window.pys.Pinterest || Pinterest;
406                return Pinterest;
407            },
408
409            setupBingObject: function () {
410                Bing = window.pys.Bing || Bing;
411                return Bing;
412            },
413
414            // Clone all object members to another and return it
415            copyProperties: function (from, to) {
416                for (var key in from) {
417                    if("function" == typeof from[key]) {
418                        continue;
419                    }
420                    to[key] = from[key];
421                }
422                return to;
423            },
424
425            manageCookies: function () {
426                let expires = parseInt(options.cookie_duration); //  days
427                let queryVars = getQueryVars();
428                let landing = window.location.href.split('?')[0];
429                try {
430                    // save data for first visit
431                    if(Cookies.get('pys_first_visit') === undefined) {
432                        Cookies.set('pys_first_visit', true, { expires: expires });
433                        Cookies.set('pysTrafficSource', getTrafficSource(), { expires: expires });
434                        Cookies.set('pys_landing_page',landing,{ expires: expires });
435                        $.each(utmTerms, function (index, name) {
436                            if (queryVars.hasOwnProperty(name)) {
437                                Cookies.set('pys_' + name, queryVars[name], { expires: expires });
438                            } else {
439                                Cookies.remove('pys_' + name)
440                            }
441                        });
442                        $.each(utmId,function(index,name) {
443                            if (queryVars.hasOwnProperty(name)) {
444                                Cookies.set('pys_' + name, queryVars[name], { expires: expires });
445                            } else {
446                                Cookies.remove('pys_' + name)
447                            }
448                        })
449                    }
450
451                    // save data for last visit if it new session
452                    if(isNewSession) {
453                        Cookies.set('last_pysTrafficSource', getTrafficSource(), { expires: expires });
454                        $.each(utmTerms, function (index, name) {
455                            if (queryVars.hasOwnProperty(name)) {
456                                Cookies.set('last_pys_' + name, queryVars[name], { expires: expires });
457                            } else {
458                                Cookies.remove('last_pys_' + name)
459                            }
460                        });
461                        $.each(utmId,function(index,name) {
462                            if (queryVars.hasOwnProperty(name)) {
463                                Cookies.set('last_pys_' + name, queryVars[name], { expires: expires });
464                            } else {
465                                Cookies.remove('last_pys_' + name)
466                            }
467                        })
468                        Cookies.set('last_pys_landing_page',landing,{ expires: expires });
469                    }
470                } catch (e) {
471                    console.error(e);
472                }
473            },
474            // clone object
475            clone: function(obj) {
476                var copy;
477
478                // Handle the 3 simple types, and null or undefined
479                if (null == obj || "object" != typeof obj) return obj;
480
481                // Handle Date
482                if (obj instanceof Date) {
483                    copy = new Date();
484                    copy.setTime(obj.getTime());
485                    return copy;
486                }
487
488                // Handle Array
489                if (obj instanceof Array) {
490                    copy = [];
491                    for (var i = 0, len = obj.length; i < len; i++) {
492                        if("function" == typeof obj[i]) {
493                            continue;
494                        }
495                        copy[i] = Utils.clone(obj[i]);
496                    }
497                    return copy;
498                }
499
500                // Handle Object
501                if (obj instanceof Object) {
502                    copy = {};
503                    for (var attr in obj) {
504                        if (obj.hasOwnProperty(attr)) {
505                            if("function" == typeof obj[attr]) {
506                                continue;
507                            }
508                            copy[attr] = Utils.clone(obj[attr]);
509                        }
510                    }
511                    return copy;
512                }
513
514                return obj;
515            },
516
517            // Returns array of elements with given tag name
518            getTagsAsArray: function (tag) {
519                return [].slice.call(document.getElementsByTagName(tag));
520            },
521
522            getRequestParams: function () {
523                return [];
524            },
525
526            /**
527             * CUSTOM EVENTS
528             */
529
530            setupMouseOverClickEvents: function (eventId, triggers) {
531
532                // Non-default binding used to avoid situations when some code in external js
533                // stopping events propagation, eg. returns false, and our handler will never called
534                $(document).onFirst('mouseover', triggers.join(','), function () {
535
536                    // do not fire event multiple times
537                    if ($(this).hasClass('pys-mouse-over-' + eventId)) {
538                        return true;
539                    } else {
540                        $(this).addClass('pys-mouse-over-' + eventId);
541                    }
542
543                    Utils.fireDynamicEvent(eventId);
544
545                });
546
547            },
548
549            setupCSSClickEvents: function (eventId, triggers) {
550
551                // Non-default binding used to avoid situations when some code in external js
552                // stopping events propagation, eg. returns false, and our handler will never called
553                $(document).onFirst('click', triggers.join(','), function () {
554                    Utils.fireTriggerEvent(eventId);
555                });
556            },
557
558            setupURLClickEvents: function () {
559
560                // Non-default binding used to avoid situations when some code in external js
561                // stopping events propagation, eg. returns false, and our handler will never called
562                $('a[data-pys-event-id]').onFirst('click', function (evt) {
563
564                    $(this).attr('data-pys-event-id').split(',').forEach(function (eventId) {
565
566                        eventId = parseInt(eventId);
567
568                        if (isNaN(eventId) === false) {
569                            Utils.fireTriggerEvent(eventId);
570                        }
571
572                    });
573
574                });
575
576
577            },
578
579            setupScrollPosEvents: function (eventId, triggers) {
580
581                var scrollPosThresholds = {},
582                    docHeight = $(document).height() - $(window).height();
583
584                // convert % to absolute positions
585                $.each(triggers, function (index, scrollPos) {
586
587                    // convert % to pixels
588                    scrollPos = docHeight * scrollPos / 100;
589                    scrollPos = Math.round(scrollPos);
590
591                    scrollPosThresholds[scrollPos] = eventId;
592
593                });
594
595                $(document).on("scroll",function () {
596
597                    var scrollPos = $(window).scrollTop();
598
599                    $.each(scrollPosThresholds, function (threshold, eventId) {
600
601                        // position has not reached yes
602                        if (scrollPos <= threshold) {
603                            return true;
604                        }
605
606                        // fire event only once
607                        if (eventId === null) {
608                            return true;
609                        } else {
610                            scrollPosThresholds[threshold] = null;
611                        }
612
613                        Utils.fireTriggerEvent(eventId);
614
615                    });
616
617                });
618
619
620            },
621            setupCommentEvents : function (eventId,triggers) {
622                $('form.comment-form').on("submit",function () {
623                    Utils.fireTriggerEvent(eventId);
624                });
625            },
626
627            /**
628             * Events
629             */
630
631            fireTriggerEvent: function (eventId) {
632
633                if (!options.triggerEvents.hasOwnProperty(eventId)) {
634                    return;
635                }
636
637                var event = {};
638                var events = options.triggerEvents[eventId];
639
640                if (events.hasOwnProperty('facebook')) {
641                    event = events.facebook;
642                    Facebook.fireEvent(event.name, event);
643                }
644
645                if (events.hasOwnProperty('ga')) {
646                    event = events.ga;
647                    Analytics.fireEvent(event.name, event);
648                }
649
650                if (events.hasOwnProperty('pinterest')) {
651                    event = events.pinterest;
652                    Pinterest.fireEvent(event.name, event);
653                }
654
655                if (events.hasOwnProperty('bing')) {
656                    event = events.bing;
657                    Bing.fireEvent(event.name, event);
658                }
659            },
660
661            fireStaticEvents: function (pixel) {
662
663                if (options.staticEvents.hasOwnProperty(pixel)) {
664
665                    $.each(options.staticEvents[pixel], function (eventName, events) {
666                        $.each(events, function (index, eventData) {
667
668                            eventData.fired = eventData.fired || false;
669
670                            if (!eventData.fired) {
671
672                                var fired = false;
673
674                                // fire event
675                                if ('facebook' === pixel) {
676                                    fired = Facebook.fireEvent(eventData.name, eventData);
677                                } else if ('ga' === pixel) {
678                                    fired = Analytics.fireEvent(eventData.name, eventData);
679                                } else if ('pinterest' === pixel) {
680                                    fired = Pinterest.fireEvent(eventData.name, eventData);
681                                } else if ('bing' === pixel) {
682                                    fired = Bing.fireEvent(eventData.name, eventData);
683                                }
684
685                                // prevent event double event firing
686                                eventData.fired = fired;
687
688                            }
689
690                        });
691                    });
692
693                }
694
695            },
696
697            /**
698             * Load tag's JS
699             *
700             * @link: https://developers.google.com/analytics/devguides/collection/gtagjs/
701             * @link: https://developers.google.com/analytics/devguides/collection/gtagjs/custom-dims-mets
702             */
703            loadGoogleTag: function (id) {
704
705                if (!gtag_loaded) {
706
707                    (function (window, document, src) {
708                        var a = document.createElement('script'),
709                            m = document.getElementsByTagName('script')[0];
710                        a.async = 1;
711                        a.src = src;
712                        m.parentNode.insertBefore(a, m);
713                    })(window, document, '//www.googletagmanager.com/gtag/js?id=' + id);
714
715                    window.dataLayer = window.dataLayer || [];
716                    window.gtag = window.gtag || function gtag() {
717                        dataLayer.push(arguments);
718                    };
719
720                    gtag('js', new Date());
721
722                    gtag_loaded = true;
723
724                }
725
726            },
727
728            /**
729             * GDPR
730             */
731
732            loadPixels: function () {
733
734                if (options.gdpr.ajax_enabled && !options.gdpr.consent_magic_integration_enabled) {
735
736                    // retrieves actual PYS GDPR filters values which allow to avoid cache issues
737                    $.get({
738                        url: options.ajaxUrl,
739                        dataType: 'json',
740                        data: {
741                            action: 'pys_get_gdpr_filters_values'
742                        },
743                        success: function (res) {
744
745                            if (res.success) {
746
747                                options.gdpr.all_disabled_by_api = res.data.all_disabled_by_api;
748                                options.gdpr.facebook_disabled_by_api = res.data.facebook_disabled_by_api;
749                                options.gdpr.analytics_disabled_by_api = res.data.analytics_disabled_by_api;
750                                options.gdpr.google_ads_disabled_by_api = res.data.google_ads_disabled_by_api;
751                                options.gdpr.pinterest_disabled_by_api = res.data.pinterest_disabled_by_api;
752                                options.gdpr.bing_disabled_by_api = res.data.bing_disabled_by_api;
753
754                            }
755
756                            loadPixels();
757
758                        }
759                    });
760
761                } else {
762                    loadPixels();
763                }
764
765            },
766
767            consentGiven: function (pixel) {
768
769                /**
770                 * ConsentMagic
771                 */
772                if (options.gdpr.consent_magic_integration_enabled && typeof CS_Data !== "undefined" ) {
773
774                    var test_prefix = CS_Data.test_prefix;
775                    if ((typeof CS_Data.cs_google_analytics_consent_mode !== "undefined" && CS_Data.cs_google_analytics_consent_mode == 1) && pixel == 'analytics') {
776                        return true;
777                    }
778                    if ((typeof CS_Data.cs_google_ads_consent_mode !== "undefined" && CS_Data.cs_google_ads_consent_mode == 1) && pixel == 'google_ads') {
779                        return true;
780                    }
781
782                    if ( CS_Data.cs_cache_enabled == 1 ) {
783                        var substring = "cs_enabled_cookie_term";
784                        var theCookies = document.cookie.split(';');
785
786                        for (var i = 1 ; i <= theCookies.length; i++) {
787                            if ( theCookies[ i - 1 ].indexOf( substring ) !== -1 ) {
788                                var categoryCookie = theCookies[ i - 1 ].replace( 'cs_enabled_cookie_term' + test_prefix + '_', '' );
789                                categoryCookie = Number( categoryCookie.replace( /\D+/g, "" ) );
790                                var cs_cookie_val = Cookies.get( 'cs_enabled_cookie_term' + test_prefix + '_' + categoryCookie );
791
792                                if ( categoryCookie === CS_Data.cs_script_cat.facebook && pixel == 'facebook' ) {
793                                    if ( cs_cookie_val == 'yes' ) {
794                                        return true;
795                                    } else {
796                                        return false;
797                                    }
798                                } else if ( categoryCookie === CS_Data.cs_script_cat.bing && pixel == 'bing' ) {
799                                    if ( cs_cookie_val == 'yes' ) {
800                                        return true;
801                                    } else {
802                                        return false;
803                                    }
804                                } else if ( categoryCookie === CS_Data.cs_script_cat.analytics && pixel == 'analytics' ) {
805                                    if ( cs_cookie_val == 'yes' ) {
806                                        return true;
807                                    } else {
808                                        return false;
809                                    }
810                                } else if ( categoryCookie === CS_Data.cs_script_cat.gads && pixel == 'google_ads' ) {
811                                    if ( cs_cookie_val == 'yes' ) {
812                                        return true;
813                                    } else {
814                                        return false;
815                                    }
816                                } else if ( categoryCookie === CS_Data.cs_script_cat.pinterest && pixel == 'pinterest' ) {
817                                    if ( cs_cookie_val == 'yes' ) {
818                                        return true;
819                                    } else {
820                                        return false;
821                                    }
822                                } else if ( categoryCookie === CS_Data.cs_script_cat.tiktok && pixel == 'tiktok' ) {
823                                    if ( cs_cookie_val == 'yes' ) {
824                                        return true;
825                                    } else {
826                                        return false;
827                                    }
828                                }
829                            }
830                        }
831                    } else {
832                        var cs_cookie = Cookies.get('cs_viewed_cookie_policy'+test_prefix);
833                        if (typeof cs_cookie === 'undefined' || cs_cookie === 'yes') {
834                            return true;
835                        }
836                    }
837
838                    return false;
839
840                }
841
842                /**
843                 * Real Cookie Banner
844                 */
845                if(options.gdpr.real_cookie_banner_integration_enabled) {
846                    var consentApi = window.consentApi;
847                    if (consentApi) {
848                        switch (pixel) {
849                            case "analytics":
850                                return consentApi.consentSync("http", "_ga", "*").cookieOptIn;
851                            case "facebook":
852                                return consentApi.consentSync("http", "_fbp", "*").cookieOptIn;
853                            case "pinterest":
854                                return consentApi.consentSync("http", "_pinterest_sess", ".pinterest.com").cookieOptIn;
855                            default:
856                                return true;
857                        }
858                    }
859                }
860
861                /**
862                 * Cookiebot
863                 */
864                if (options.gdpr.cookiebot_integration_enabled && typeof Cookiebot !== 'undefined') {
865
866                    var cookiebot_consent_category = options.gdpr['cookiebot_' + pixel + '_consent_category'];
867
868                    if (options.gdpr[pixel + '_prior_consent_enabled']) {
869                        if (Cookiebot.consented === false || Cookiebot.consent[cookiebot_consent_category]) {
870                            return true;
871                        }
872                    } else {
873                        if (Cookiebot.consent[cookiebot_consent_category]) {
874                            return true;
875                        }
876                    }
877
878                    return false;
879
880                }
881
882                /**
883                 * Cookie Notice
884                 */
885                if (options.gdpr.cookie_notice_integration_enabled && typeof cnArgs !== 'undefined') {
886
887                    var cn_cookie = Cookies.get(cnArgs.cookieName);
888
889                    if (options.gdpr[pixel + '_prior_consent_enabled']) {
890                        if (typeof cn_cookie === 'undefined' || cn_cookie === 'true') {
891                            return true;
892                        }
893                    } else {
894                        if (cn_cookie === 'true') {
895                            return true;
896                        }
897                    }
898
899                    return false;
900
901                }
902
903                /**
904                 * Cookie Law Info
905                 */
906                if (options.gdpr.cookie_law_info_integration_enabled) {
907
908                    var cli_cookie = Cookies.get('viewed_cookie_policy');
909
910                    if (options.gdpr[pixel + '_prior_consent_enabled']) {
911                        if (typeof cli_cookie === 'undefined' || cli_cookie === 'yes') {
912                            return true;
913                        }
914                    } else {
915                        if (cli_cookie === 'yes') {
916                            return true;
917                        }
918                    }
919
920                    return false;
921
922                }
923
924                return true;
925
926            },
927
928            setupGdprCallbacks: function () {
929                /**
930                 * ConsentMagic
931                 */
932                if (options.gdpr.consent_magic_integration_enabled && typeof CS_Data !== "undefined") {
933                    var test_prefix = CS_Data.test_prefix,
934                        cs_refresh_after_consent = false,
935                        substring = "cs_enabled_cookie_term";
936
937                    if (CS_Data.cs_refresh_after_consent == 1) {
938                        cs_refresh_after_consent = CS_Data.cs_refresh_after_consent;
939                    }
940
941                    if (!cs_refresh_after_consent) {
942                        var theCookies = document.cookie.split(';');
943                        for (var i = 1 ; i <= theCookies.length; i++) {
944                            if (theCookies[i-1].indexOf(substring) !== -1) {
945                                var categoryCookie = theCookies[i-1].replace('cs_enabled_cookie_term'+test_prefix+'_','');
946                                categoryCookie = Number(categoryCookie.replace(/\D+/g,""));
947                                var cs_cookie_val = Cookies.get('cs_enabled_cookie_term'+test_prefix+'_'+categoryCookie);
948                                if(cs_cookie_val == 'yes') {
949                                    if (categoryCookie === CS_Data.cs_script_cat.facebook) {
950                                        Facebook.loadPixel();
951                                    } 
952                                    
953                                    if (categoryCookie === CS_Data.cs_script_cat.bing) {
954                                        Bing.loadPixel();
955                                    }
956
957                                    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)) {
958
959                                        Analytics.loadPixel();
960                                    }
961                                    
962                                     if (categoryCookie === CS_Data.cs_script_cat.pinterest) {
963                                        Pinterest.loadPixel();
964                                    }
965                                } else {
966                                    if (categoryCookie === CS_Data.cs_script_cat.facebook) {
967                                        Facebook.disable();
968                                    } 
969                                    
970                                     if (categoryCookie === CS_Data.cs_script_cat.bing) {
971                                        Bing.disable();
972                                    }
973                                    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)) {
974                                        Analytics.disable();
975                                    }
976                                    
977                                     if (categoryCookie === CS_Data.cs_script_cat.pinterest) {
978                                        Pinterest.disable();
979                                    }
980                                }
981                                if (Cookies.get('cs_enabled_advanced_matching') == 'yes') {
982                                    Facebook.loadPixel();
983                                }
984                            }
985                        }
986
987                        $(document).on('click','.cs_action_btn',function(e) {
988                            e.preventDefault();
989                            var elm = $(this),
990                                button_action = elm.attr('data-cs_action');
991
992                            if(button_action === 'allow_all') {
993                                Facebook.loadPixel();
994                                Bing.loadPixel();
995                                Analytics.loadPixel();
996                                Pinterest.loadPixel();
997                            } else if(button_action === 'disable_all') {
998                                Facebook.disable();
999                                Bing.disable();
1000                                if(CS_Data.cs_google_analytics_consent_mode == 0 || typeof CS_Data.cs_google_analytics_consent_mode == "undefined")
1001                                {
1002                                    Analytics.disable();
1003                                }
1004                                Pinterest.disable();
1005                            }
1006                        });
1007                    }
1008                }
1009                /**
1010                 * Real Cookie Banner
1011                 */
1012                if(options.gdpr.real_cookie_banner_integration_enabled) {
1013                    var consentApi = window.consentApi;
1014                    if (consentApi) {
1015                        consentApi.consent("http", "_ga", "*")
1016                            .then(Analytics.loadPixel.bind(Analytics), Analytics.disable.bind(Analytics));
1017                        consentApi.consent("http", "_fbp", "*")
1018                            .then(Facebook.loadPixel.bind(Facebook), Facebook.disable.bind(Facebook));
1019                        consentApi.consent("http", "_pinterest_sess", ".pinterest.com")
1020                            .then(Pinterest.loadPixel.bind(Pinterest), Pinterest.disable.bind(Pinterest));
1021                    }
1022                }
1023                /**
1024                 * Cookiebot
1025                 */
1026                if (options.gdpr.cookiebot_integration_enabled && typeof Cookiebot !== 'undefined') {
1027
1028                    window.addEventListener("CookiebotOnConsentReady", function() {
1029                        if (Cookiebot.consent.marketing) {
1030                            Facebook.loadPixel();
1031                            Bing.loadPixel();
1032                            Pinterest.loadPixel();
1033
1034                        }
1035                        if (Cookiebot.consent.statistics) {
1036                            Analytics.loadPixel();
1037                        }
1038                        if (!Cookiebot.consent.marketing) {
1039                            Facebook.disable();
1040                            Pinterest.disable();
1041                            Bing.disable()
1042                        }
1043                        if (!Cookiebot.consent.statistics) {
1044                            Analytics.disable();
1045                        }
1046                    });
1047
1048                }
1049
1050                /**
1051                 * Cookie Notice
1052                 */
1053                if (options.gdpr.cookie_notice_integration_enabled) {
1054
1055                    $(document).onFirst('click', '.cn-set-cookie', function () {
1056
1057                        if ($(this).data('cookie-set') === 'accept') {
1058                            Facebook.loadPixel();
1059                            Analytics.loadPixel();
1060                            Pinterest.loadPixel();
1061                            Bing.loadPixel();
1062                        } else {
1063                            Facebook.disable();
1064                            Analytics.disable();
1065                            Pinterest.disable();
1066                            Bing.disable();
1067                        }
1068
1069                    });
1070
1071                    $(document).onFirst('click', '.cn-revoke-cookie', function () {
1072                        Facebook.disable();
1073                        Analytics.disable();
1074                        Pinterest.disable();
1075                        Bing.disable();
1076                    });
1077
1078                }
1079
1080                /**
1081                 * Cookie Law Info
1082                 */
1083                if (options.gdpr.cookie_law_info_integration_enabled) {
1084
1085                    $(document).onFirst('click', '#cookie_action_close_header', function () {
1086                        Facebook.loadPixel();
1087                        Analytics.loadPixel();
1088                        Pinterest.loadPixel();
1089                        Bing.loadPixel();
1090                    });
1091
1092                    $(document).onFirst('click', '#cookie_action_close_header_reject', function () {
1093                        Facebook.disable();
1094                        Analytics.disable();
1095                        Pinterest.disable();
1096                        Bing.disable();
1097                    });
1098
1099                }
1100
1101            },
1102
1103            /**
1104             * DOWNLOAD DOCS
1105             */
1106
1107            getLinkExtension: function (link) {
1108
1109                // Remove anchor, query string and everything before last slash
1110                link = link.substring(0, (link.indexOf("#") === -1) ? link.length : link.indexOf("#"));
1111                link = link.substring(0, (link.indexOf("?") === -1) ? link.length : link.indexOf("?"));
1112                link = link.substring(link.lastIndexOf("/") + 1, link.length);
1113
1114                // If there's a period left in the URL, then there's a extension
1115                if (link.length > 0 && link.indexOf('.') !== -1) {
1116                    link = link.substring(link.indexOf(".") + 1); // Remove everything but what's after the first period
1117                    return link;
1118                } else {
1119                    return "";
1120                }
1121            },
1122
1123            getLinkFilename: function (link) {
1124
1125                // Remove anchor, query string and everything before last slash
1126                link = link.substring(0, (link.indexOf("#") === -1) ? link.length : link.indexOf("#"));
1127                link = link.substring(0, (link.indexOf("?") === -1) ? link.length : link.indexOf("?"));
1128                link = link.substring(link.lastIndexOf("/") + 1, link.length);
1129
1130                // If there's a period left in the URL, then there's a extension
1131                if (link.length > 0 && link.indexOf('.') !== -1) {
1132                    return link;
1133                } else {
1134                    return "";
1135                }
1136            },
1137            /**
1138             * Enrich
1139             */
1140            isCheckoutPage: function () {
1141                return $('body').hasClass('woocommerce-checkout') || document.querySelector('.woocommerce-checkout') ||
1142                    $('body').hasClass('edd-checkout');
1143            },
1144            addCheckoutFields : function() {
1145                var utm = "";
1146                var utms = getUTMs()
1147
1148                $.each(utmTerms, function (index, name) {
1149                    if(index > 0) {
1150                        utm+="|";
1151                    }
1152                    utm+=name+":"+utms[name];
1153                });
1154                var utmIdList = "";
1155                var utmsIds = getUTMId()
1156                $.each(utmId, function (index, name) {
1157                    if(index > 0) {
1158                        utmIdList+="|";
1159                    }
1160                    utmIdList+=name+":"+utmsIds[name];
1161                });
1162                var utmIdListLast = "";
1163                var utmsIdsLast = getUTMId(true)
1164                $.each(utmId, function (index, name) {
1165                    if(index > 0) {
1166                        utmIdListLast+="|";
1167                    }
1168                    utmIdListLast+=name+":"+utmsIdsLast[name];
1169                });
1170
1171
1172                var utmLast = "";
1173                var utmsLast = getUTMs(true)
1174                $.each(utmTerms, function (index, name) {
1175                    if(index > 0) {
1176                        utmLast+="|";
1177                    }
1178                    utmLast+=name+":"+utmsLast[name];
1179                });
1180
1181                var dateTime = getDateTime();
1182                var landing = Cookies.get('pys_landing_page');
1183                var lastLanding = Cookies.get('last_pys_landing_page');
1184                var trafic = Cookies.get('pysTrafficSource');
1185                var lastTrafic = Cookies.get('last_pysTrafficSource');
1186
1187                var $form = null;
1188                if($('body').hasClass('woocommerce-checkout')) {
1189                    $form = $("form.woocommerce-checkout");
1190                } else {
1191                    $form = $("#edd_purchase_form");
1192                }
1193                var inputs = {'pys_utm':utm,
1194                    'pys_utm_id':utmIdList,
1195                    'pys_browser_time':dateTime.join("|"),
1196                    'pys_landing':landing,
1197                    'pys_source':trafic,
1198                    'pys_order_type': $(".wcf-optin-form").length > 0 ? "wcf-optin" : "normal",
1199
1200                    'last_pys_landing':lastLanding,
1201                    'last_pys_source':lastTrafic,
1202                    'last_pys_utm':utmLast,
1203                    'last_pys_utm_id':utmIdListLast,
1204                }
1205
1206                Object.keys(inputs).forEach(function(key,index) {
1207                    $form.append("<input type='hidden' name='"+key+"' value='"+inputs[key]+"' /> ");
1208                });
1209
1210
1211            }
1212        };
1213
1214    }(options);
1215
1216    var Facebook = function (options) {
1217
1218
1219        var defaultEventTypes = [
1220            'PageView',
1221            'ViewContent',
1222            'Search',
1223            'AddToCart',
1224            'AddToWishlist',
1225            'InitiateCheckout',
1226            'AddPaymentInfo',
1227            'Purchase',
1228            'Lead',
1229
1230            'Subscribe',
1231            'CustomizeProduct',
1232            'FindLocation',
1233            'StartTrial',
1234            'SubmitApplication',
1235            'Schedule',
1236            'Contact',
1237            'Donate'
1238        ];
1239
1240        var initialized = false;
1241
1242        // fire server side event gdpr plugin installed
1243        var isApiDisabled = options.gdpr.all_disabled_by_api ||
1244            options.gdpr.facebook_disabled_by_api ||
1245            options.gdpr.cookiebot_integration_enabled ||
1246            options.gdpr.consent_magic_integration_enabled ||
1247            options.gdpr.cookie_notice_integration_enabled ||
1248            options.gdpr.cookie_law_info_integration_enabled;
1249
1250        /**
1251         *
1252         * @param allData
1253         * @param params
1254         * @returns {string | null}
1255         */
1256        function sendFbServerEvent(allData,name,params) {
1257            let eventId = null;
1258            if(options.facebook.serverApiEnabled) {
1259
1260                if(allData.e_id === "woo_remove_from_cart" || allData.e_id === "woo_add_to_cart_on_button_click") {// server event will sended from hook
1261                    let isAddToCartFromJs =  options.woo.hasOwnProperty("addToCartCatchMethod")
1262                        && options.woo.addToCartCatchMethod === "add_cart_js";
1263
1264                    if(isAddToCartFromJs || allData.e_id !== "woo_add_to_cart_on_button_click") {
1265                        Facebook.updateEventId(allData.name);
1266                        allData.eventID = Facebook.getEventId(allData.name);
1267                    } else {
1268                        // not update eventID for woo_add_to_cart_on_button_click,
1269                        // web event created by ajax from server
1270                    }
1271                } else {
1272                    if(  options.facebook.ajaxForServerEvent
1273                        || isApiDisabled
1274                        || allData.delay > 0
1275                        || allData.type !== "static")
1276                    { // send event from server if they was bloc by gdpr or need send with delay
1277                        allData.eventID = pys_generate_token(36);
1278                        var json = {
1279                            action: 'pys_api_event',
1280                            pixel: 'facebook',
1281                            event: name,
1282                            data:params,
1283                            ids:options.facebook.pixelIds,
1284                            eventID:allData.eventID,
1285                            url:window.location.href,
1286                            ajax_event:options.ajax_event
1287                        };
1288                        if(allData.hasOwnProperty('woo_order')) {
1289                            json['woo_order'] = allData.woo_order;
1290                        }
1291                        if(allData.hasOwnProperty('edd_order')) {
1292                            json['edd_order'] = allData.edd_order;
1293                        }
1294
1295                        if(name == 'PageView') {
1296                            let expires = parseInt(options.cookie_duration);
1297                            var currentTimeInSeconds=Date.now();
1298                            var randomNum = Math.floor(1000000000 + Math.random() * 9000000000);
1299                            timeoutDelay = 0;
1300                            if(allData.delay > 0)
1301                            {
1302                                timeoutDelay = allData.delay;
1303                            }
1304                            if(!Cookies.get('_fbp'))
1305                            {
1306                                timeoutDelay = 100;
1307                            }
1308                            if(getUrlParameter('fbclid') && !Cookies.get('_fbc'))
1309                            {
1310                                timeoutDelay = 100;
1311                            }
1312                            setTimeout(function(){
1313                                if(!Cookies.get('_fbp'))
1314                                {
1315                                    Cookies.set('_fbp','fb.1.'+currentTimeInSeconds+'.'+randomNum,  { expires: expires })
1316                                }
1317                                if(getUrlParameter('fbclid') && !Cookies.get('_fbc'))
1318                                {
1319                                    Cookies.set('_fbc', 'fb.1.'+currentTimeInSeconds+'.'+getUrlParameter('fbclid'),  { expires: expires })
1320                                }
1321                                jQuery.ajax( {
1322                                    type: 'POST',
1323                                    url: options.ajaxUrl,
1324                                    data: json,
1325                                    headers: {
1326                                        'Cache-Control': 'no-cache'
1327                                    },
1328                                    success: function(){},
1329                                });
1330                            },timeoutDelay)
1331                        }
1332                        else
1333                        {
1334                            jQuery.ajax( {
1335                                type: 'POST',
1336                                url: options.ajaxUrl,
1337                                data: json,
1338                                headers: {
1339                                    'Cache-Control': 'no-cache'
1340                                },
1341                                success: function(){},
1342                            });
1343                        }
1344                    }
1345                }
1346                eventId = allData.eventID
1347            }
1348
1349            return eventId;
1350        }
1351
1352        function fireEvent(name, allData) {
1353
1354            if(typeof window.pys_event_data_filter === "function" && window.pys_disable_event_filter(name,'facebook')) {
1355                return;
1356            }
1357
1358            var actionType = defaultEventTypes.includes(name) ? 'track' : 'trackCustom';
1359            var data = allData.params;
1360            var params = {};
1361            var arg = {};
1362            Utils.copyProperties(data, params);
1363
1364            let eventId = sendFbServerEvent(allData,name,params)
1365
1366
1367            if("hCR" === name) {
1368                return;
1369            }
1370
1371            if (options.debug) {
1372                console.log('[Facebook] ' + name, params,"eventID",eventId);
1373            }
1374
1375            if(eventId != null) {
1376                arg.eventID = eventId;
1377            }
1378
1379            fbq(actionType, name, params,arg);
1380        }
1381
1382        /**
1383         * Public API
1384         */
1385        return {
1386            tag: function() {
1387                return "facebook";
1388            },
1389            isEnabled: function () {
1390                return options.hasOwnProperty('facebook');
1391            },
1392
1393            disable: function () {
1394                initialized = false;
1395            },
1396
1397            /**
1398             * Load pixel's JS
1399             */
1400            loadPixel: function () {
1401
1402                if (initialized || !this.isEnabled() || !Utils.consentGiven('facebook')) {
1403                    return;
1404                }
1405
1406                !function (f, b, e, v, n, t, s) {
1407                    if (f.fbq) return;
1408                    n = f.fbq = function () {
1409                        n.callMethod ?
1410                            n.callMethod.apply(n, arguments) : n.queue.push(arguments)
1411                    };
1412                    if (!f._fbq) f._fbq = n;
1413                    n.push = n;
1414                    n.loaded = !0;
1415                    n.version = '2.0';
1416                    n.agent = 'dvpixelyoursite';
1417                    n.queue = [];
1418                    t = b.createElement(e);
1419                    t.async = !0;
1420                    t.src = v;
1421                    s = b.getElementsByTagName(e)[0];
1422                    s.parentNode.insertBefore(t, s)
1423                }(window,
1424                    document, 'script', 'https://connect.facebook.net/en_US/fbevents.js');
1425
1426                // initialize pixel
1427                options.facebook.pixelIds.forEach(function (pixelId) {
1428
1429                    if (options.facebook.removeMetadata) {
1430                        fbq('set', 'autoConfig', false, pixelId);
1431                    }
1432                    if (options.gdpr.consent_magic_integration_enabled && typeof CS_Data !== "undefined") {
1433                        if(options.facebook.advancedMatching.length === 0) {
1434                            fbq('init', pixelId);
1435                        } else {
1436                            var cs_advanced_matching = Cookies.get('cs_enabled_advanced_matching'+test_prefix);
1437                            if (jQuery('#cs_enabled_advanced_matching'+test_prefix).length > 0) {
1438                                if (cs_advanced_matching == 'yes') {
1439                                    fbq('init', pixelId, options.facebook.advancedMatching);
1440                                } else {
1441                                    fbq('init', pixelId);
1442                                }
1443                            } else {
1444                                fbq('init', pixelId, options.facebook.advancedMatching);
1445                            }
1446                        }
1447                    } else {
1448                        if (options.facebook.advancedMatching.length === 0) {
1449                            fbq('init', pixelId);
1450                        } else {
1451                            fbq('init', pixelId, options.facebook.advancedMatching);
1452                        }
1453                    }
1454                });
1455
1456                initialized = true;
1457
1458                Utils.fireStaticEvents('facebook');
1459
1460            },
1461
1462            fireEvent: function (name, data) {
1463
1464                if (!initialized || !this.isEnabled()) {
1465                    return false;
1466                }
1467
1468                data.delay = data.delay || 0;
1469                data.params = data.params || {};
1470
1471                if (data.delay === 0) {
1472
1473                    fireEvent(name, data);
1474
1475                } else {
1476
1477                    setTimeout(function (name, params) {
1478                        fireEvent(name, params);
1479                    }, data.delay * 1000, name, data);
1480
1481                }
1482
1483                return true;
1484
1485            },
1486
1487            onCommentEvent: function (event) {
1488                this.fireEvent(event.name, event);
1489            },
1490
1491            onDownloadEvent: function (event) {
1492                this.fireEvent(event.name, event);
1493            },
1494
1495            onFormEvent: function (event) {
1496
1497                this.fireEvent(event.name, event);
1498
1499            },
1500
1501            onWooAddToCartOnButtonEvent: function (product_id) {
1502
1503                if(!options.dynamicEvents.woo_add_to_cart_on_button_click.hasOwnProperty(this.tag()))
1504                    return;
1505                var event = options.dynamicEvents.woo_add_to_cart_on_button_click[this.tag()];
1506
1507                if (window.pysWooProductData.hasOwnProperty(product_id)) {
1508                    if (window.pysWooProductData[product_id].hasOwnProperty('facebook')) {
1509                        event = Utils.copyProperties(event, {})
1510                        Utils.copyProperties(window.pysWooProductData[product_id]['facebook'].params, event.params)
1511                        this.fireEvent(event.name, event);
1512                    }
1513                }
1514            },
1515
1516            onWooAddToCartOnSingleEvent: function (product_id, qty, product_type, $form) {
1517
1518                window.pysWooProductData = window.pysWooProductData || [];
1519                if(!options.dynamicEvents.woo_add_to_cart_on_button_click.hasOwnProperty(this.tag()))
1520                    return;
1521                var event = Utils.clone(options.dynamicEvents.woo_add_to_cart_on_button_click[this.tag()]);
1522
1523                if (product_type === Utils.PRODUCT_VARIABLE && !options.facebook.wooVariableAsSimple) {
1524                    product_id = parseInt($form.find('input[name="variation_id"]').val());
1525                }
1526
1527                if (window.pysWooProductData.hasOwnProperty(product_id)) {
1528                    if (window.pysWooProductData[product_id].hasOwnProperty('facebook')) {
1529
1530
1531                        Utils.copyProperties(window.pysWooProductData[product_id]['facebook'].params, event.params);
1532
1533                        var groupValue = 0;
1534                        if(product_type === Utils.PRODUCT_GROUPED ) {
1535                            $form.find(".woocommerce-grouped-product-list .qty").each(function(index){
1536                                var childId = $(this).attr('name').replaceAll("quantity[","").replaceAll("]","");
1537                                var quantity = parseInt($(this).val());
1538                                if(isNaN(quantity)) {
1539                                    quantity = 0;
1540                                }
1541                                var childItem = window.pysWooProductData[product_id]['facebook'].grouped[childId];
1542
1543                                if(quantity == 0) {
1544                                    event.params.content_ids.forEach(function(el,index,array) {
1545                                        if(el == childItem.content_id) {
1546                                            array.splice(index, 1);
1547                                        }
1548                                    });
1549                                }
1550
1551                                if(event.params.hasOwnProperty('contents')) {
1552                                    event.params.contents.forEac
1552h(function(el,index,array) {
1553                                        if(el.id == childItem.content_id) {
1554                                            if(quantity > 0){
1555                                                el.quantity = quantity;
1556                                            } else {
1557                                                array.splice(index, 1);
1558                                            }
1559                                        }
1560                                    });
1561                                }
1562
1563
1564                                groupValue += childItem.price * quantity;
1565                            });
1566                            if(groupValue == 0) return; // skip if no items selected
1567                        }
1568
1569                        // maybe customize value option
1570                        if (options.woo.addToCartOnButtonValueEnabled && options.woo.addToCartOnButtonValueOption !== 'global') {
1571
1572                            if(product_type === Utils.PRODUCT_GROUPED) {
1573                                event.params.value = groupValue;
1574                            } else if(product_type === Utils.PRODUCT_BUNDLE) {
1575                                var data = $(".bundle_form .bundle_data").data("bundle_form_data");
1576                                var items_sum = getBundlePriceOnSingleProduct(data);
1577                                event.params.value = (parseInt(data.base_price) + items_sum )* qty;
1578                            } else {
1579                                event.params.value = event.params.value * qty;
1580                            }
1581                        }
1582
1583                        // only when non Facebook for WooCommerce logic used
1584                        if (event.params.hasOwnProperty('contents') && product_type !== Utils.PRODUCT_GROUPED) {
1585                            event.params.contents[0].quantity = qty;
1586                        }
1587
1588                        this.fireEvent(event.name, event);
1589
1590                    }
1591                }
1592            },
1593
1594            onWooRemoveFromCartEvent: function (event) {
1595                this.fireEvent(event.name, event);
1596            },
1597
1598            onEddAddToCartOnButtonEvent: function (download_id, price_index, qty) {
1599
1600                if(!options.dynamicEvents.edd_add_to_cart_on_button_click.hasOwnProperty(this.tag()))
1601                    return;
1602                var event = Utils.clone(options.dynamicEvents.edd_add_to_cart_on_button_click[this.tag()]);
1603
1604                if (window.pysEddProductData.hasOwnProperty(download_id)) {
1605
1606                    var index;
1607
1608                    if (price_index) {
1609                        index = download_id + '_' + price_index;
1610                    } else {
1611                        index = download_id;
1612                    }
1613
1614                    if (window.pysEddProductData[download_id].hasOwnProperty(index)) {
1615                        if (window.pysEddProductData[download_id][index].hasOwnProperty('facebook')) {
1616
1617
1618                            Utils.copyProperties(window.pysEddProductData[download_id][index]['facebook']["params"], event.params)
1619
1620                            // maybe customize value option
1621                            if (options.edd.addToCartOnButtonValueEnabled && options.edd.addToCartOnButtonValueOption !== 'global') {
1622                                event.params.value = event.params.value * qty;
1623                            }
1624
1625                            // update contents qty param
1626                            var contents = event.params.contents;
1627                            contents[0].quantity = qty;
1628                            event.params.contents = contents;
1629
1630                            this.fireEvent(event.name,event);
1631
1632                        }
1633                    }
1634
1635                }
1636
1637            },
1638
1639            onEddRemoveFromCartEvent: function (event) {
1640                this.fireEvent(event.name, event);
1641            },
1642            onPageScroll: function (event) {
1643                this.fireEvent(event.name, event);
1644            },
1645            onTime: function (event) {
1646                this.fireEvent(event.name, event);
1647            },
1648            initEventIdCookies: function (key) {
1649                var ids = {};
1650                ids[key] = pys_generate_token(36)
1651                Cookies.set('pys_fb_event_id', JSON.stringify(ids));
1652            },
1653            updateEventId:function(key) {
1654                var cooData = Cookies.get("pys_fb_event_id")
1655                if(cooData === undefined) {
1656                    this.initEventIdCookies(key);
1657                } else {
1658                    var data = JSON.parse(cooData);
1659                    data[key] = pys_generate_token(36);
1660                    Cookies.set('pys_fb_event_id', JSON.stringify(data) );
1661                }
1662            },
1663
1664            getEventId:function (key) {
1665                var data = Cookies.get("pys_fb_event_id");
1666                if(data === undefined) {
1667                    this.initEventIdCookies(key);
1668                    data = Cookies.get("pys_fb_event_id");
1669                }
1670                return JSON.parse(data)[key];
1671            },
1672        };
1673
1674    }(options);
1675
1676    var Analytics = function (options) {
1677
1678        var initialized = false;
1679
1680        /**
1681         * Fires event
1682         *
1683         * @link: https://developers.google.com/analytics/devguides/collection/gtagjs/sending-data
1684         * @link: https://developers.google.com/analytics/devguides/collection/gtagjs/events
1685         * @link: https://developers.google.com/gtagjs/reference/event
1686         * @link: https://developers.google.com/gtagjs/reference/parameter
1687         *
1688         * @link: https://developers.google.com/analytics/devguides/collection/gtagjs/custom-dims-mets
1689         *
1690         * @param name
1691         * @param data
1692         */
1693        function fireEvent(name, data) {
1694
1695            if(typeof window.pys_event_data_filter === "function" && window.pys_disable_event_filter(name,'ga')) {
1696                return;
1697            }
1698
1699            var eventParams = Utils.copyProperties(data, {});
1700
1701            var _fireEvent = function (tracking_id,name,params) {
1702
1703                params['send_to'] = tracking_id;
1704
1705                if (options.debug) {
1706                    console.log('[Google Analytics #' + tracking_id + '] ' + name, params);
1707                }
1708
1709                gtag('event', name, params);
1710
1711            };
1712
1713            options.ga.trackingIds.forEach(function (tracking_id) {
1714                var copyParams = Utils.copyProperties(eventParams, {}); // copy params because mapParamsTov4 can modify it
1715                var params = mapParamsTov4(tracking_id,name,copyParams)
1716                _fireEvent(tracking_id,name,params);
1717            });
1718
1719        }
1720        function mapParamsTov4(tag,name,param) {
1721            //GA4 automatically collects a number of parameters for all events
1722            delete param.page_title;
1723            delete param.event_url;
1724            delete param.landing_page;
1725            // end
1726            if(isv4(tag)) {
1727                delete param.traffic_source;
1728                delete param.event_category;
1729                delete param.event_label;
1730                delete param.ecomm_prodid;
1731                delete param.ecomm_pagetype;
1732                delete param.ecomm_totalvalue;
1733                if(name === 'search') {
1734                    param['search'] = param.search_term;
1735                    delete param.search_term;
1736                    delete param.non_interaction;
1737                    delete param.dynx_itemid;
1738                    delete param.dynx_pagetype;
1739                    delete param.dynx_totalvalue;
1740                }
1741            } else {
1742
1743                switch (name) {
1744
1745                    case 'Comment' :
1746                    case 'login' :
1747                    case 'sign_up' :
1748                    case 'EmailClick' :
1749                    case 'TelClick' : {
1750                        let params = {
1751                            event_category: "Key Actions",
1752                            event_action: name,
1753                             non_interaction: param.non_interaction,
1754                        }
1755                        return params;
1756                    }
1757                    case 'Form' : {
1758                        let params = {
1759                            event_category: "Key Actions",
1760                            event_action: name,
1761                            non_interaction: param.non_interaction,
1762                        }
1763                        var formClass = (typeof param.form_class != 'undefined') ? 'class: ' + param.form_class : '';
1764                        if(formClass != "") {
1765                            params["event_label"] = formClass;
1766                        }
1767                        return params;
1768                    }
1769                    case 'Download' : {
1770                        let params = {
1771                            event_category: "Key Actions",
1772                            event_action: name,
1773                            event_label: param.download_name,
1774                              non_interaction: param.non_interaction,
1775                        }
1776                        return params;
1777                    }
1778                    case 'TimeOnPage' :
1779                    case 'PageScroll' : {
1780                        let params = {
1781                            event_category: "Key Actions",
1782                            event_action: name,
1783                            event_label: document.title,
1784                              non_interaction: param.non_interaction,
1785                        }
1786                        return params;
1787                    }
1788                    case 'search' : {
1789                        let params = {
1790                            event_category: "Key Actions",
1791                            event_action: name,
1792                            event_label: param.search_term,
1793                              non_interaction: param.non_interaction,
1794                        }
1795                        return params;
1796                    }
1797                }
1798
1799                //delete standard params
1800
1801                delete param.post_type;
1802                delete param.post_id;
1803                delete param.plugin;
1804                delete param.user_role;
1805                delete param.cartlows;
1806                delete param.cartflows_flow;
1807                delete param.cartflows_step;
1808            }
1809            return param;
1810        }
1811
1812        function isv4(tag) {
1813            return tag.indexOf('G') === 0;
1814        }
1815
1816        /**
1817         * Public API
1818         */
1819        return {
1820            tag: function() {
1821                return "ga";
1822            },
1823            isEnabled: function () {
1824                return options.hasOwnProperty('ga');
1825            },
1826
1827            disable: function () {
1828                initialized = false;
1829            },
1830
1831            loadPixel: function () {
1832
1833                if (initialized || !this.isEnabled() || !Utils.consentGiven('analytics')) {
1834                    return;
1835                }
1836
1837                Utils.loadGoogleTag(options.ga.trackingIds[0]);
1838
1839                var config = {
1840                    'link_attribution': options.ga.enhanceLinkAttr,
1841                    'anonymize_ip': options.ga.anonimizeIP
1842                };
1843
1844                // Cross-Domain tracking
1845                if (options.ga.crossDomainEnabled) {
1846                    config.linker = {
1847                        accept_incoming: options.ga.crossDomainAcceptIncoming,
1848                        domains: options.ga.crossDomainDomains
1849                    };
1850                }
1851
1852
1853
1854                // configure tracking ids
1855                options.ga.trackingIds.forEach(function (trackingId,index) {
1856                    config.debug_mode = options.ga.isDebugEnabled.includes("index_" + index);
1857                    if(isv4(trackingId)) {
1858                        if(options.ga.disableAdvertisingFeatures) {
1859                            config.allow_google_signals = false
1860                        }
1861                        if(options.ga.disableAdvertisingPersonalization) {
1862                            config.allow_ad_personalization_signals = false
1863                        }
1864                    }
1865                    if (options.gdpr.cookiebot_integration_enabled && typeof Cookiebot !== 'undefined') {
1866
1867                        var cookiebot_consent_category = options.gdpr['cookiebot_analytics_consent_category'];
1868                        if (options.gdpr['analytics_prior_consent_enabled']) {
1869                            if (Cookiebot.consented === true && Cookiebot.consent[cookiebot_consent_category]) {
1870                                gtag('config', trackingId, config);
1871                            }
1872                        } else {
1873                            if (Cookiebot.consent[cookiebot_consent_category]) {
1874                                gtag('config', trackingId, config);
1875                            }
1876                        }
1877
1878                    }
1879                    else
1880                    {
1881                        gtag('config', trackingId, config);
1882                    }
1883                });
1884
1885                initialized = true;
1886
1887                Utils.fireStaticEvents('ga');
1888
1889            },
1890
1891            fireEvent: function (name, data) {
1892
1893                if (!initialized || !this.isEnabled()) {
1894                    return false;
1895                }
1896
1897                data.delay = data.delay || 0;
1898                data.params = data.params || {};
1899
1900                if (data.delay === 0) {
1901
1902                    fireEvent(name, data.params);
1903
1904                } else {
1905
1906                    setTimeout(function (name, params) {
1907                        fireEvent(name, params);
1908                    }, data.delay * 1000, name, data.params);
1909
1910                }
1911
1912                return true;
1913
1914            },
1915
1916            onCommentEvent: function (event) {
1917                this.fireEvent(event.name, event);
1918            },
1919
1920            onDownloadEvent: function (event) {
1921                this.fireEvent(event.name, event);
1922            },
1923
1924            onFormEvent: function (event) {
1925                this.fireEvent(event.name, event);
1926            },
1927
1928            onWooAddToCartOnButtonEvent: function (product_id) {
1929
1930                if(!options.dynamicEvents.woo_add_to_cart_on_button_click.hasOwnProperty(this.tag()))
1931                    return;
1932                var event = Utils.clone(options.dynamicEvents.woo_add_to_cart_on_button_click[this.tag()]);
1933
1934                if (window.pysWooProductData.hasOwnProperty(product_id)) {
1935                    if (window.pysWooProductData[product_id].hasOwnProperty('ga')) {
1936                        Utils.copyProperties(window.pysWooProductData[product_id]['ga'].params, event.params)
1937                        this.fireEvent(event.name, event);
1938                    }
1939                }
1940
1941
1942            },
1943
1944            onWooAddToCartOnSingleEvent: function (product_id, qty, product_type, $form) {
1945
1946                window.pysWooProductData = window.pysWooProductData || [];
1947
1948                if(!options.dynamicEvents.woo_add_to_cart_on_button_click.hasOwnProperty(this.tag()))
1949                    return;
1950                var event = Utils.clone(options.dynamicEvents.woo_add_to_cart_on_button_click[this.tag()]);
1951
1952                if (product_type === Utils.PRODUCT_VARIABLE && !options.ga.wooVariableAsSimple) {
1953                    product_id = parseInt($form.find('input[name="variation_id"]').val());
1954                }
1955
1956                if (window.pysWooProductData.hasOwnProperty(product_id)) {
1957                    if (window.pysWooProductData[product_id].hasOwnProperty('ga')) {
1958
1959                        Utils.copyProperties(window.pysWooProductData[product_id]['ga'].params, event.params);
1960                        if(product_type === Utils.PRODUCT_GROUPED ) {
1961                            var groupValue = 0;
1962                            $form.find(".woocommerce-grouped-product-list .qty").each(function(index){
1963                                var childId = $(this).attr('name').replaceAll("quantity[","").replaceAll("]","");
1964                                var quantity = parseInt($(this).val());
1965                                if(isNaN(quantity)) {
1966                                    quantity = 0;
1967                                }
1968                                var childItem = window.pysWooProductData[product_id]['ga'].grouped[childId];
1969                                // update quantity
1970                                event.params.items.forEach(function(el,index,array) {
1971                                    if(el.id == childItem.content_id) {
1972                                        if(quantity > 0){
1973                                            el.quantity = quantity;
1974                                        } else {
1975                                            array.splice(index, 1);
1976                                        }
1977                                    }
1978                                });
1979                                groupValue += childItem.price * quantity;
1980                            });
1981                            if(options.woo.addToCartOnButtonValueEnabled &&
1982                                options.woo.addToCartOnButtonValueOption !== 'global' &&
1983                                event.params.hasOwnProperty('ecomm_totalvalue')) {
1984                                event.params.ecomm_totalvalue = groupValue;
1985                            }
1986
1987                            if(groupValue == 0) return;
1987 // skip if no items selected
1988                        } else {
1989                            // update items qty param
1990                            event.params.items[0].quantity = qty;
1991                        }
1992
1993                        // maybe customize value option
1994                        if (options.woo.addToCartOnButtonValueEnabled &&
1995                            options.woo.addToCartOnButtonValueOption !== 'global' &&
1996                            product_type !== Utils.PRODUCT_GROUPED)
1997                        {
1998                            if(event.params.hasOwnProperty('ecomm_totalvalue')) {
1999                                event.params.ecomm_totalvalue = event.params.items[0].price * qty;
2000                            }
2001
2002                        }
2003
2004
2005                        this.fireEvent(event.name, event);
2006                    }
2007                }
2008
2009            },
2010
2011            onWooRemoveFromCartEvent: function (event) {
2012
2013                this.fireEvent(event.name, event);
2014
2015            },
2016
2017            onEddAddToCartOnButtonEvent: function (download_id, price_index, qty) {
2018
2019                if(!options.dynamicEvents.edd_add_to_cart_on_button_click.hasOwnProperty(this.tag()))
2020                    return;
2021                var event = Utils.clone(options.dynamicEvents.edd_add_to_cart_on_button_click[this.tag()]);
2022
2023
2024                if (window.pysEddProductData.hasOwnProperty(download_id)) {
2025
2026                    var index;
2027
2028                    if (price_index) {
2029                        index = download_id + '_' + price_index;
2030                    } else {
2031                        index = download_id;
2032                    }
2033
2034                    if (window.pysEddProductData[download_id].hasOwnProperty(index)) {
2035                        if (window.pysEddProductData[download_id][index].hasOwnProperty('ga')) {
2036
2037                            Utils.copyProperties(window.pysEddProductData[download_id][index]['ga'].params, event.params);
2038
2039                            // update items qty param
2040                            event.params.items[0].quantity = qty;
2041
2042                            this.fireEvent(event.name,event);
2043
2044                        }
2045                    }
2046
2047                }
2048
2049            },
2050
2051            onEddRemoveFromCartEvent: function (event) {
2052                this.fireEvent(event.name, event);
2053            },
2054            onPageScroll: function (event) {
2055                this.fireEvent(event.name, event);
2056            },
2057            onTime: function (event) {
2058                this.fireEvent(event.name, event);
2059            },
2060
2061        };
2062
2063    }(options);
2064
2065    window.pys = window.pys || {};
2066    window.pys.Facebook = Facebook;
2067    window.pys.Analytics = Analytics;
2068    window.pys.Utils = Utils;
2069
2070
2071
2072
2073    $(document).ready(function () {
2074
2075        if($("#pys_late_event").length > 0) {
2076            var events =  JSON.parse($("#pys_late_event").attr("dir"));
2077            for(var key in events) {
2078                var event = {};
2079                event[events[key].e_id] = [events[key]];
2080                if(options.staticEvents.hasOwnProperty(key)) {
2081                    Object.assign(options.staticEvents[key], event);
2082                } else {
2083                    options.staticEvents[key] = event;
2084                }
2085
2086            }
2087        }
2088
2089        var Pinterest = Utils.setupPinterestObject();
2090        var Bing = Utils.setupBingObject();
2091
2092        if((options.woo.enabled || options.edd.enabled) && (options.woo.enabled_save_data_to_orders || options.edd.enabled_save_data_to_orders))
2093        {
2094            Utils.manageCookies();
2095        }
2096        else
2097        {
2098            Cookies.remove('pys_first_visit')
2099            Cookies.remove('pysTrafficSource')
2100            Cookies.remove('pys_landing_page')
2101            Cookies.remove('last_pys_landing_page')
2102            Cookies.remove('last_pysTrafficSource')
2103            Cookies.remove('pys_start_session')
2104            Cookies.remove('pys_session_limit')
2105
2106            $.each(Utils.utmTerms, function (index, name) {
2107                Cookies.remove('pys_' + name)
2108            });
2109            $.each(Utils.utmId,function(index,name) {
2110                Cookies.remove('pys_' + name)
2111            })
2112            $.each(Utils.utmTerms, function (index, name) {
2113                Cookies.remove('last_pys_' + name)
2114            });
2115            $.each(Utils.utmId,function(index,name) {
2116                Cookies.remove('last_pys_' + name)
2117            });
2118        }
2119        Utils.setupGdprCallbacks();
2120        // page scroll event
2121        if ( options.dynamicEvents.hasOwnProperty("automatic_event_scroll")
2122        ) {
2123
2124            var singlePageScroll = function () {
2125
2126
2127                var docHeight = $(document).height() - $(window).height();
2128                var isFired = false;
2129
2130                if (options.dynamicEvents.hasOwnProperty("automatic_event_scroll")) {
2131                    var pixels = Object.keys(options.dynamicEvents.automatic_event_scroll);
2132                    for(var i = 0;i<pixels.length;i++) {
2133                        var event = Utils.clone(options.dynamicEvents.automatic_event_scroll[pixels[i]]);
2134                        var scroll = Math.round(docHeight * event.scroll_percent / 100)// convert % to absolute positions
2135
2136                        if(scroll < $(window).scrollTop()) {
2137                            Utils.copyProperties(Utils.getRequestParams(), event.params);
2138                            getPixelBySlag(pixels[i]).onPageScroll(event);
2139                            isFired = true
2140                        }
2141                    }
2142                }
2143                if(isFired) {
2144                    $(document).off("scroll",singlePageScroll);
2145                }
2146            }
2147            $(document).on("scroll",singlePageScroll);
2148        }
2149
2150
2151        if (options.dynamicEvents.hasOwnProperty("automatic_event_time_on_page")) {
2152            var pixels = Object.keys(options.dynamicEvents.automatic_event_time_on_page);
2153            var time = options.dynamicEvents.automatic_event_time_on_page[pixels[0]].time_on_page; // the same for all pixel
2154            setTimeout(function(){
2155                for(var i = 0;i<pixels.length;i++) {
2156                    var event = Utils.clone(options.dynamicEvents.automatic_event_time_on_page[pixels[i]]);
2157                    Utils.copyProperties(Utils.getRequestParams(), event.params);
2158                    getPixelBySlag(pixels[i]).onTime(event);
2159                }
2160            },time*1000);
2161        }
2162
2163        // setup Click Event
2164        if (options.dynamicEvents.hasOwnProperty("automatic_event_download")) {
2165
2166            $(document).onFirst('click', 'a, button, input[type="button"], input[type="submit"]', function (e) {
2167
2168                var $elem = $(this);
2169
2170                // Download
2171                if(options.dynamicEvents.hasOwnProperty("automatic_event_download")
2172                ) {
2173                    var isFired = false;
2174                    if ($elem.is('a')) {
2175                        var href = $elem.attr('href');
2176                        if (typeof href !== "string") {
2177                            return;
2178                        }
2179                        href = href.trim();
2180                        var extension = Utils.getLinkExtension(href);
2181                        var track_download = false;
2182
2183                        if (extension.length > 0) {
2184
2185                            if(options.dynamicEvents.hasOwnProperty("automatic_event_download") ) {
2186                                var pixels = Object.keys(options.dynamicEvents.automatic_event_download);
2187                                for (var i = 0; i < pixels.length; i++) {
2188                                    var event = Utils.clone(options.dynamicEvents.automatic_event_download[pixels[i]]);
2189                                    var extensions = event.extensions;
2190                                    if (extensions.includes(extension)) {
2191
2192                                        if(pixels[i] == "tiktok") {
2193                                            getPixelBySlag(pixels[i]).fireEvent(tikEvent.name, event);
2194                                        } else {
2195                                            if (options.enable_remove_download_url_param) {
2196                                                href = href.split('?')[0];
2197                                            }
2198                                            event.params.download_url = href;
2199                                            event.params.download_type = extension;
2200                                            event.params.download_name = Utils.getLinkFilename(href);
2201                                            getPixelBySlag(pixels[i]).onDownloadEvent(event);
2202                                        }
2203
2204                                        isFired = true;
2205                                    }
2206                                }
2207                            }
2208                        }
2209                    }
2210                    if(isFired) { // prevent duplicate events on the same element
2211                        return;
2212                    }
2213                }
2214            });
2215        }
2216
2217
2218        // setup Dynamic events
2219        $.each(options.triggerEventTypes, function (triggerType, events) {
2220
2221            $.each(events, function (eventId, triggers) {
2222
2223                switch (triggerType) {
2224                    case 'url_click':
2225                        //@see: Utils.setupURLClickEvents()
2226                        break;
2227
2228                    case 'css_click':
2229                        Utils.setupCSSClickEvents(eventId, triggers);
2230                        break;
2231
2232                    case 'css_mouseover':
2233                        Utils.setupMouseOverClickEvents(eventId, triggers);
2234                        break;
2235
2236                    case 'scroll_pos':
2237                        Utils.setupScrollPosEvents(eventId, triggers);
2238                        break;
2239                    case 'comment':
2240                        Utils.setupCommentEvents(eventId, triggers);
2241                        break;
2242                }
2243
2244            });
2245
2246        });
2247        // setup WooCommerce events
2248        if (options.woo.enabled) {
2249
2250            // WooCommerce AddToCart
2251            if (options.dynamicEvents.hasOwnProperty("woo_add_to_cart_on_button_click")
2252                && options.woo.hasOwnProperty("addToCartCatchMethod")
2253                && options.woo.addToCartCatchMethod === "add_cart_js"
2254            ) {
2255
2256                // Loop, any kind of "simple" product, except external
2257                $('.add_to_cart_button:not(.product_type_variable,.product_type_bundle,.single_add_to_cart_button)').on("click",function (e) {
2258
2259                    var product_id = $(this).data('product_id');
2260
2261                    if (typeof product_id !== 'undefined') {
2262                        Facebook.onWooAddToCartOnButtonEvent(product_id);
2263                        Analytics.onWooAddToCartOnButtonEvent(product_id);
2264                        Pinterest.onWooAddToCartOnButtonEvent(product_id);
2265                        Bing.onWooAddToCartOnButtonEvent(product_id);
2266                    }
2267
2268                });
2269
2270                // Single Product
2271                // tap try to https://stackoverflow.com/questions/30990967/on-tap-click-event-firing-twice-how-to-avoid-it
2272                //  $(document) not work
2273                $('body').onFirst('click','button.single_add_to_cart_button,.single_add_to_cart_button',function (e) {
2274
2275                    var $button = $(this);
2276
2277                    if ($button.hasClass('disabled')) {
2278                        return;
2279                    }
2280
2281                    var $form = $button.closest('form');
2282
2283                    var product_type = Utils.PRODUCT_SIMPLE;
2284
2285                    if ($form.length === 0) {
2286                        return ;
2287                    } else if ($form.hasClass('variations_form')) {
2288                        product_type = Utils.PRODUCT_VARIABLE;
2289                    } else if($form.hasClass('bundle_form')) {
2290                        product_type = Utils.PRODUCT_BUNDLE;
2291                    } else if($form.hasClass('grouped_form')) {
2292                        product_type = Utils.PRODUCT_GROUPED;
2293                    }
2294
2295
2296
2297
2298                    var product_id;
2299                    var qty;
2300
2301                    if (product_type === Utils.PRODUCT_GROUPED) {
2302                        qty = 1;
2303                        product_id = parseInt($form.find('*[name="add-to-cart"]').val());
2304                    } else if (product_type === Utils.PRODUCT_VARIABLE) {
2305                        product_id = parseInt($form.find('*[name="add-to-cart"]').val());
2306                        var qtyTag = $form.find('input[name="quantity"]');
2307                        if(qtyTag.length <= 0) {
2308                            qtyTag = $form.find('select[name="quantity"]');
2309                        }
2310                        qty = parseInt(qtyTag.val());
2311                    } else {
2312                        product_id = parseInt($form.find('*[name="add-to-cart"]').val());
2313                        var qtyTag = $form.find('input[name="quantity"]');
2314                        if(qtyTag.length <= 0) {
2315                            qtyTag = $form.find('select[name="quantity"]');
2316                        }
2317                        qty = parseInt(qtyTag.val());
2318                    }
2319
2320                    Facebook.onWooAddToCartOnSingleEvent(product_id, qty, product_type, $form);
2321                    Analytics.onWooAddToCartOnSingleEvent(product_id, qty, product_type, $form);
2322
2323                    Pinterest.onWooAddToCartOnSingleEvent(product_id, qty, product_type, false, $form);
2324                    Bing.onWooAddToCartOnSingleEvent(product_id, qty, product_type, false, $form);
2325
2326                });
2327
2328            }
2329
2330            // WooCommerce RemoveFromCart
2331            if (options.dynamicEvents.hasOwnProperty("woo_remove_from_cart")) {
2332
2333                $('body').on('click', options.woo.removeFromCartSelector, function (e) {
2334
2335                    var $a = $(e.currentTarget),
2336                        href = $a.attr('href');
2337
2338                    // extract cart item hash from remove button URL
2339                    var regex = new RegExp("[\\?&]remove_item=([^&#]*)"),
2340                        results = regex.exec(href);
2341
2342                    if (results !== null) {
2343
2344                        var item_hash = results[1];
2345
2346                        if (options.dynamicEvents["woo_remove_from_cart"].hasOwnProperty(item_hash)) {
2347                            var events = options.dynamicEvents["woo_remove_from_cart"][item_hash];
2348                            Utils.fireEventForAllPixel("onWooRemoveFromCartEvent",events)
2349                        }
2350
2351                    }
2352
2353                });
2354            }
2355        }
2356
2357        // setup EDD events
2358        if (options.edd.enabled) {
2359
2360            // EDD AddToCart
2361            if (options.dynamicEvents.hasOwnProperty("edd_add_to_cart_on_button_click")) {
2362
2363                $('form.edd_download_purchase_form .edd-add-to-cart').on("click",function (e) {
2364
2365                    var $button = $(this);
2366                    var $form = $button.closest('form');
2367                    var variable_price = $button.data('variablePrice'); // yes/no
2368                    var price_mode = $button.data('priceMode'); // single/multi
2369                    var ids = [];
2370                    var quantities = [];
2371                    var qty;
2372                    var id;
2373
2374                    if (variable_price === 'yes' && price_mode === 'multi') {
2375
2376                        id = $form.find('input[name="download_id"]').val();
2377
2378                        // get selected variants
2379                        $.each($form.find('input[name="edd_options[price_id][]"]:checked'), function (i, el) {
2380                            ids.push(id + '_' + $(el).val());
2381                        });
2382
2383                        // get qty for selected variants
2384                        $.each(ids, function (i, variant_id) {
2385
2386                            var variant_index = variant_id.split('_', 2);
2387                            qty = $form.find('input[name="edd_download_quantity_' + variant_index[1] + '"]').val();
2388
2389                            if (typeof qty !== 'undefined') {
2390                                quantities.push(qty);
2391                            } else {
2392                                quantities.push(1);
2393                            }
2394
2395                        });
2396
2397                    } else if (variable_price === 'yes' && price_mode === 'single') {
2398
2399                        id = $form.find('input[name="download_id"]').val();
2400                        ids.push(id + '_' + $form.find('input[name="edd_options[price_id][]"]:checked').val());
2401
2402                        qty = $form.find('input[name="edd_download_quantity"]').val();
2403
2404                        if (typeof qty !== 'undefined') {
2405                            quantities.push(qty);
2406                        } else {
2407                            quantities.push(1);
2408                        }
2409
2410                    } else {
2411
2412                        ids.push($button.data('downloadId'));
2413
2414                        qty = $form.find('input[name="edd_download_quantity"]').val();
2415
2416                        if (typeof qty !== 'undefined') {
2417                            quantities.push(qty);
2418                        } else {
2419                            quantities.push(1);
2420                        }
2421                    }
2422
2423                    // fire event for each download/variant
2424                    $.each(ids, function (i, download_id) {
2425
2426                        var q = parseInt(quantities[i]);
2427                        var variant_index = download_id.toString().split('_', 2);
2428                        var price_index;
2429
2430                        if (variant_index.length === 2) {
2431                            download_id = variant_index[0];
2432                            price_index = variant_index[1];
2433                        }
2434
2435                        Facebook.onEddAddToCartOnButtonEvent(download_id, price_index, q);
2436                        Analytics.onEddAddToCartOnButtonEvent(download_id, price_index, q);
2437                        Pinterest.onEddAddToCartOnButtonEvent(download_id, price_index, q);
2438                        Bing.onEddAddToCartOnButtonEvent(download_id, price_index, q);
2439
2440                    });
2441
2442                });
2443
2444            }
2445
2446
2447            // EDD RemoveFromCart
2448            if (options.dynamicEvents.hasOwnProperty("edd_remove_from_cart") ) {
2449
2450                $('form#edd_checkout_cart_form .edd_cart_remove_item_btn').on("click",function (e) {
2451
2452                    var href = $(this).attr('href');
2453                    if(href) {
2454                        var key = href.substring(href.indexOf('=') + 1).charAt(0);
2455                        if (options.dynamicEvents.edd_remove_from_cart.hasOwnProperty(key)) {
2456                            var events = options.dynamicEvents.edd_remove_from_cart[key];
2457                            Utils.fireEventForAllPixel("onEddRemoveFromCartEvent",events)
2458                        }
2459                    }
2460                });
2461
2462            }
2463
2464        }
2465
2466        // setup Comment Event
2467        if (options.dynamicEvents.hasOwnProperty("automatic_event_c
2467omment")
2468        ) {
2469
2470            $('form.comment-form').on("submit",function () {
2471                if (options.dynamicEvents.hasOwnProperty("automatic_event_comment")) {
2472                    var pixels = Object.keys(options.dynamicEvents.automatic_event_comment);
2473                    for (var i = 0; i < pixels.length; i++) {
2474                        var event = Utils.clone(options.dynamicEvents.automatic_event_comment[pixels[i]]);
2475                        Utils.copyProperties(Utils.getRequestParams(), event.params);
2476                        getPixelBySlag(pixels[i]).onCommentEvent(event);
2477                    }
2478                }
2479            });
2480
2481        }
2482
2483
2484        // setup Form Event
2485        if ( options.dynamicEvents.hasOwnProperty("automatic_event_form")) {
2486
2487            $(document).onFirst('submit', 'form', function (e) {
2488
2489                var $form = $(this);
2490
2491                // exclude WP forms
2492                if ($form.hasClass('comment-form') || $form.hasClass('search-form') || $form.attr('id') === 'adminbarsearch') {
2493                    return;
2494                }
2495
2496                // exclude Woo forms
2497                if ($form.hasClass('woocommerce-product-search') || $form.hasClass('cart') || $form.hasClass('woocommerce-cart-form') ||
2498                    $form.hasClass('woocommerce-shipping-calculator') || $form.hasClass('checkout') || $form.hasClass('checkout_coupon')) {
2499                    return;
2500                }
2501
2502                // exclude EDD forms
2503                if ($form.hasClass('edd_form') || $form.hasClass('edd_download_purchase_form')) {
2504                    return;
2505                }
2506// exclude CF7 forms
2507                if ($form.hasClass('wpcf7-form')) {
2508                    return;
2509                }
2510                // exclude Forminator forms
2511                if ($form.hasClass('forminator-custom-form') || $form.hasClass('forminator_ajax')) {
2512                    return;
2513                }
2514                // exclude WPforms forms
2515                if ($form.hasClass('wpforms-form') || $form.hasClass('wpforms-ajax-form')) {
2516                    return;
2517                }
2518                // exclude Formidable forms
2519                /*if ($form.hasClass('frm-show-form')) {
2520                    return;
2521                }*/
2522                // exclude Ninja Forms forms
2523                if ($form.parent().hasClass('nf-form-layout')) {
2524                    return;
2525                }
2526                // exclude Fluent forms
2527                if ($form.hasClass('frm-fluent-form')) {
2528                    return;
2529                }
2530                if(!options.enable_success_send_form) {
2531                    var params = {
2532                        form_id: $form.attr('id'),
2533                        form_class: $form.attr('class'),
2534                        text: $form.find('[type="submit"]').is('input') ?
2535                            $form.find('[type="submit"]').val() : $form.find('[type="submit"]').text()
2536                    };
2537
2538                    if (options.dynamicEvents.hasOwnProperty("automatic_event_form")) {
2539                        var pixels = Object.keys(options.dynamicEvents.automatic_event_form);
2540                        for (var i = 0; i < pixels.length; i++) {
2541                            var event = Utils.clone(options.dynamicEvents.automatic_event_form[pixels[i]]);
2542
2543                            if (pixels[i] === "tiktok") {
2544                                getPixelBySlag(pixels[i]).fireEvent(event.name, event);
2545                            } else {
2546                                Utils.copyProperties(params, event.params,)
2547                                Utils.copyProperties(Utils.getRequestParam
2547s(), event.params);
2548                                getPixelBySlag(pixels[i]).onFormEvent(event);
2549                            }
2550                        }
2551                    }
2552                }
2553            });
2554
2555            document.addEventListener( 'wpcf7mailsent', function( event ) {
2556                var form_id = event.detail.contactFormId;
2557                sendFormAction($(event.target), form_id);
2558            }, false );
2559            //Forminator
2560            $(document).on( 'forminator:form:submit:success', function( event ){
2561                var form_id = $(event.target).find('input[name="form_id"]').val();
2562                sendFormAction($(event.target), form_id);
2563            });
2564
2565            //WPForm
2566            $('form.wpforms-form').on('wpformsAjaxSubmitSuccess', (event) => {
2567                var form_id = $(event.target).attr('data-formid');
2568                sendFormAction($(event.target), form_id);
2569            })
2570            $(document).on( 'frmFormComplete', function( event, form, response ) {
2571                const form_id = $(form).find('input[name="form_id"]').val();
2572                sendFormAction($(event.target), form_id);
2573            });
2574            // Ninja Forms
2575            $(document).onFirst('nfFormSubmitResponse', function (event, data) {
2576                const form_id = data.response.data.form_id;
2577                sendFormAction($(event.target), form_id);
2578            });
2579
2580            var fluentForms = $('form.frm-fluent-form');
2581            fluentForms.each(function() {
2582                var $form = $(this);
2583                $form.on('fluentform_submission_success', function(event) {
2584                    var $formItem = $(this);
2585                    var form_id = $formItem.attr('data-form_id');
2586                    sendFormAction($(event.target), form_id);
2587                });
2588            });
2589
2590        }
2591
2592
2593        // load pixel APIs
2594        Utils.loadPixels();
2595        // setup Enrich content
2596        if(Utils.isCheckoutPage()) {
2597            Utils.addCheckoutFields();
2598        }
2599    });
2600
2601    var sendFormAction = function (form_target, formId){
2602        var params = {
2603            form_id: formId,
2604            text: form_target.find('[type="submit"]').is('input') ? form_target.find('[type="submit"]').val() :
2605                form_target.find('.forminator-button-submit').text() != '' ? form_target.find('.forminator-button-submit').text() :
2606                    form_target.find('[type="submit"]').text()
2607        };
2608
2609        if (options.dynamicEvents.hasOwnProperty("automatic_event_form")) {
2610            var pixels = Object.keys(options.dynamicEvents.automatic_event_form);
2611            for (var i = 0; i < pixels.length; i++) {
2612                var event = options.dynamicEvents.automatic_event_form[pixels[i]];
2613                if (pixels[i] === "tiktok") {
2614                    getPixelBySlag(pixels[i]).fireEvent(event.name, event);
2615                } else {
2616                    Utils.copyProperties(params, event.params)
2617                    Utils.copyProperties(Utils.getRequestParams(), event.params);
2618                    getPixelBySlag(pixels[i]).onFormEvent(event);
2619                }
2620            }
2621        }
2622    }
2623
2624}(jQuery, pysOptions);
2625
2626function pys_generate_token(length){
2627    //edit the token allowed characters
2628    var a = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".split("");
2629    var b = [];
2630    for (var i=0; i<length; i++) {
2631        var j = (Math.random() * (a.length-1)).toFixed(0);
2632        b[i] = a[j];
2633    }
2634    return b.join("");
2635}
2636
2637function getBundlePriceOnSingleProduct(data) {
2638    var items_sum = 0;
2639    jQuery(".bundle_form .bundled_product").each(function(index){
2640        var id = jQuery(this).find(".cart").data("bundled_item_id");
2641        var item_price = data.prices[id];
2642        var item_quantity = jQuery(this).find(".bundled_qty").val();
2643        if(!jQuery(this).hasClass("bundled_item_optional") ||
2644            jQuery(this).find(".bundled_product_optional_checkbox input").prop('checked')) {
2645            items_sum += item_price*item_quantity;
2646        }
2647    });
2648    return items_sum;
2649}
2650
2651function getPixelBySlag(slug) {
2652    switch (slug) {
2653        case "facebook": return window.pys.Facebook;
2654        case "ga": return window.pys.Analytics;
2655        case "bing": return window.pys.Bing;
2656        case "pinterest": return window.pys.Pinterest;
2657    }
2658}
2659var getUrlParameter = function getUrlParameter(sParam) {
2660    var sPageURL = window.location.search.substring(1),
2661        sURLVariables = sPageURL.split('&'),
2662        sParameterName,
2663        i;
2664
2665    for (i = 0; i < sURLVariables.length; i++) {
2666        sParameterName = sURLVariables[i].split('=');
2667
2668        if (sParameterName[0] === sParam) {
2669            return sParameterName[1] === undefined ? true : decodeURIComponent(sParameterName[1]);
2670        }
2671    }
2672    return false;
2673};

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.