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