PageSourceSearch

https://fsfysio.dk/wp-content/plugins/pixelyoursite-pro/dist/scripts/public.js?ver=8.6.8

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

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.