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