PageSourceSearch

https://soulsweet.de/wp-content/plugins/pixelyoursite-pro/dist/scripts/public.js?ver=9.1.1

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

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.