1/* global pysOptions */ 2!function ($) { 3 4 var Pinterest = function () { 5 6 var initialized = false; 7 8 function getUtils() { 9 return window.pys.Utils; 10 } 11 12 function getOptions() { 13 return window.pysOptions; 14 } 15 16 // Flatten object for sendBeacon compatibility 17 function flattenObject(obj, prefix = '', res = {}) { 18 for (const [key, value] of Object.entries(obj)) { 19 const prefixedKey = prefix ? `${prefix}[${key}]` : key; 20 if (value !== null && typeof value === 'object' && !(value instanceof File)) { 21 flattenObject(value, prefixedKey, res); 22 } else { 23 res[prefixedKey] = value; 24 } 25 } 26 return res; 27 } 28 29 // Send server request using REST API with fallback to sendBeacon and jQuery.ajax 30 function sendServerAjaxRequest(url, data) { 31 // Check if REST API is enabled and we have the necessary data for Pinterest events 32 if (data.action === 'pys_pinterest_api_event' && getOptions().pinterest && getOptions().pinterest.serverApiEnabled) { 33 // Use REST API for Pinterest events 34 const restApiUrl = window.pysPinterestRest ? window.pysPinterestRest.restApiUrl : '/wp-json/pys-pinterest/v1/event'; 35 const nonce = window.pysPinterestRest ? window.pysPinterestRest.restNonce : ''; 36 37 // Prepare data for REST API 38 const restApiData = { 39 event: data.event, 40 event_slug: data.event_slug, 41 data: JSON.stringify(data.data || {}), 42 ids: JSON.stringify(data.ids || []), 43 eventID: data.event_id || data.eventID || '', 44 woo_order: data.woo_order || '0', 45 edd_order: data.edd_order || '0' 46 }; 47 48 // Variant A: send the actual page URL where the event happened 49 // so the server sets event_source_url to this page, not the 50 // REST endpoint. PHP applies enable_remove_source_url_params. 51 restApiData.event_source_url = data.url || window.location.href; 52 53 // Try to send using sendBeacon first (if enabled) 54 if (getOptions().hasOwnProperty('useSendBeacon') && getOptions().useSendBeacon && navigator.sendBeacon) { 55 try { 56 const formData = new URLSearchParams(); 57 for (const [key, value] of Object.entries(restApiData)) { 58 formData.append(key, value); 59 } 60 61 if (navigator.sendBeacon(restApiUrl, formData)) { 62 return; 63 } 64 } catch (e) { 65 // sendBeacon failed, continue to fetch 66 } 67 } 68 69 // Try to send using fetch with REST API 70 if (window.fetch) { 71 const headers = { 72 'Content-Type': 'application/json' 73 }; 74 75 if (nonce) { 76 headers['X-WP-Nonce'] = nonce; 77 } 78 79 fetch(restApiUrl, { 80 method: 'POST', 81 headers: headers, 82 body: JSON.stringify(restApiData) 83 }) 84 .then(response => { 85 if (!response.ok) { 86 throw new Error('REST API request failed: ' + response.status); 87 } 88 }) 89 .catch(error => { 90 // Fallback to AJAX if REST API fails 91 sendAjaxFallback(data); 92 }); 93 } else { 94 // Fallback to AJAX if fetch is not supported 95 sendAjaxFallback(data); 96 } 97 return; 98 } 99 100 // For non-Pinterest events or when REST API is disabled, use original logic 101 if (getOptions().hasOwnProperty('useSendBeacon') && getOptions().useSendBeacon && navigator.sendBeacon) { 102 try { 103 const flattenedData = flattenObject(data); 104 const formData = new URLSearchParams(); 105 106 for (const [key, value] of Object.entries(flattenedData)) { 107 if (value !== null && value !== undefined) { 108 formData.append(key, value); 109 } 110 } 111 112 if (navigator.sendBeacon(url, formData)) { 113 return; // Successfully sent via sendBeacon 114 } 115 } catch (e) { 116 // If sendBeacon fails, fall back to jQuery.ajax 117 } 118 } 119 120 // Fallback to jQuery.ajax 121 jQuery.ajax({ 122 type: 'POST', 123 url: url, 124 data: data, 125 headers: { 126 'Cache-Control': 'no-cache' 127 } 128 }); 129 } 130 131 // Fallback AJAX method for Pinterest events 132 function sendAjaxFallback(data) { 133 jQuery.ajax({ 134 type: 'POST', 135 url: getOptions().ajaxUrl, 136 data: data, 137 headers: { 138 'Cache-Control': 'no-cache' 139 } 140 }); 141 } 142 143 var notCachedEventsIds = new Array(); 144 var isAddToCartFromJs = getOptions().woo.hasOwnProperty("addToCartCatchMethod") 145 && getOptions().woo.addToCartCatchMethod === "add_cart_js"; 146 if (!isAddToCartFromJs) { 147 notCachedEventsIds.push('woo_add_to_cart_on_button_click') 148 } 149 150 function fireEvent(name, event) { 151 152 if(typeof window.pys_event_data_filter === "function" && window.pys_disable_event_filter(name,'pinterest')) { 153 return; 154 } 155 156 var data = event.params; 157 var ids = event.pixelIds.filter(function (pixelId) { 158 if (getUtils().hasOwnProperty('hideMatchingPixel')) { 159 return !getUtils().hideMatchingPixel(pixelId, 'pinterest'); 160 }else{ 161 return true; 162 } 163 }); 164 if (ids.length) { 165 var params = {}; 166 167 window.pys.Utils.copyProperties(data, params); 168 window.pys.Utils.copyProperties(window.pys.Utils.getRequestParam
168s(), params); 169 170 if (getOptions().pinterest.serverApiEnabled) { 171 if(!isAddToCartFromJs && event.e_id === "woo_add_to_cart_on_button_click" ) { 172 Pinterest.updateEventId(event.name); 173 event.eventID = getUtils().generateUniqueId(event); 174 } else if(!notCachedEventsIds.includes(event.e_id)) { 175 var isApiDisabled = getOptions().gdpr.all_disabled_by_api || 176 getOptions().gdpr.facebook_disabled_by_api || 177 getOptions().gdpr.tiktok_disabled_by_api || 178 getOptions().gdpr.cookiebot_integration_enabled || 179 getOptions().gdpr.cookie_notice_integration_enabled || 180 getOptions().gdpr.consent_magic_integration_enabled || 181 getOptions().gdpr.cookie_law_info_integration_enabled; 182 183 event.eventID = getUtils().generateUniqueId(event); 184 185 if (getOptions().ajaxForServerEvent || isApiDisabled || event.delay > 0 || event.type !== "static" || ( event.hasOwnProperty( 'ajaxFire' ) && event.ajaxFire ) ) { 186 var json = { 187 action: 'pys_pinterest_api_event', 188 pixel: Pinterest.tag(), 189 event: name, 190 event_slug: event.e_id, 191 ids: ids, 192 data: params, 193 url: window.location.href, 194 eventID: event.eventID, 195 ajax_event: getOptions().ajax_event 196 }; 197 198 if (event.hasOwnProperty('woo_order')) { 199 json['woo_order'] = event.woo_order; 200 } 201 202 if (event.hasOwnProperty('edd_order')) { 203 json['edd_order'] = event.edd_order; 204 } 205 206 if (event.e_id === "automatic_event_internal_link" 207 || event.e_id === "automatic_event_outbound_link" 208 ) { 209 setTimeout(function () { 210 sendServerAjaxRequest(getOptions().ajaxUrl, json); 211 }, 500) 212 } else if (event.type !== 'static') { 213 sendServerAjaxRequest(getOptions().ajaxUrl, json); 214 } 215 216 if ( ( event.type === 'static' && getOptions().ajaxForServerStaticEvent ) || ( event.hasOwnProperty( 'ajaxFire' ) && event.ajaxFire ) ) { 217 sendServerAjaxRequest(getOptions().ajaxUrl, json); 218 } 219 } 220 } 221 } 222 params.eventID = event.eventID; 223 224 if (getOptions().debug) { 225 console.log('[Pinterest] ' + name, params); 226 } 227 228 pintrk('track', name, params); 229 } 230 } 231 232 /** 233 * Public API 234 */ 235 return { 236 tag: function() { 237 return "pinterest"; 238 }, 239 isEnabled: function () { 240 return getOptions().hasOwnProperty('pinterest'); 241 }, 242 getHidePixel: function(){ 243 if(this.isEnabled() && getOptions().pinterest.hasOwnProperty('hide_pixels')) 244 { 245 return getOptions().pinterest.hide_pixels; 246 } 247 return []; 248 }, 249 disable: function () { 250 initialized = false; 251 }, 252 initEventIdCookies: function (key) { 253 var ids = {}; 254 ids[key] = pys_generate_token(36) 255 Cookies.set('pys_pinterest_event_id', JSON.stringify(ids)); 256 }, 257 258 updateEventId:function(key) { 259 var cooData = Cookies.get("pys_pinterest_event_id")
260 if(cooData === undefined) { 261 this.initEventIdCookies(key); 262 } else { 263 var data = JSON.parse(cooData); 264 data[key] = pys_generate_token(36); 265 Cookies.set('pys_pinterest_event_id', JSON.stringify(data) ); 266 } 267 }, 268 269 getEventId:function (key) { 270 var data = Cookies.get("pys_pinterest_event_id"); 271 if(data === undefined) { 272 this.initEventIdCookies(key); 273 data = Cookies.get("pys_pinterest_event_id"); 274 } 275 return JSON.parse(data)[key]; 276 }, 277 /** 278 * Load pixel's JS 279 * 280 * @link: https://developers.pinterest.com/docs/ad-tools/enhanced-match/ 281 */ 282 loadPixel: function () { 283 284 if (initialized || !this.isEnabled() || !getUtils().consentGiven('pinterest')) { 285 return; 286 } 287 var tagId = getOptions().pinterest.pixelIds; 288 tagId = tagId.filter(function (pixelId) { 289 if (getUtils().hasOwnProperty('hideMatchingPixel')) { 290 return !getUtils().hideMatchingPixel(pixelId, 'pinterest'); 291 }else{ 292 return true; 293 } 294 295 }); 296 if(tagId.length > 0 ) { 297 !function (e) { 298 if (!window.pintrk) { 299 window.pintrk = function () { 300 window.pintrk.queue.push(Array.prototype.slice.call(arguments)) 301 }; 302 var n = window.pintrk; 303 n.queue = [], n.version = "3.0"; 304 var t = document.createElement("script"); 305 t.async = !0, t.src = e; 306 var r = document.getElementsByTagName("script")[0]; 307 r.parentNode.insertBefore(t, r) 308 } 309 }("https://s.pinimg.com/ct/core.js"); 310 311 // initialize pixel 312 tagId.forEach(function (pixelId) { 313 pintrk('load', pixelId, {em: getOptions().pinterest.advancedMatching.em, external_id: getOptions().pinterest.advancedMatching.external_id, np: 'pixelyoursite'}); 314 pintrk('page'); 315 }); 316 317 initialized = true; 318 319 getUtils().fireStaticEvents('pinterest'); 320 } 321 }, 322 323 fireEvent: function (name, data) { 324 325 if (!initialized || !this.isEnabled()) { 326 return false; 327 } 328 329 data.delay = data.delay || 0; 330 data.params = data.params || {}; 331 332 if (data.delay === 0) { 333 334 fireEvent(name, data); 335 336 } else { 337 338 setTimeout(function (name, params) { 339 fireEvent(name, params); 340 }, data.delay * 1000, name, data); 341 342 } 343 344 345 }, 346 347 onAdSenseEvent: function (event) { 348 this.fireEvent(event.name, event); 349 }, 350 351 onClickEvent: function (event) { 352 this.fireEvent(event.name, event); 353 }, 354 355 onWatchVideo: function (event) { 356 this.fireEvent(event.name, event); 357 }, 358 359 onCommentEvent: function (event) { 360 this.fireEvent(event.name, event); 361 }, 362 363 onFormEvent: function (event) { 364 this.fireEvent(event.name, event); 365 }, 366 367 onDownloadEvent: function (event) { 368 this.fireEvent(event.name, event); 369 }, 370 371 onWooAddToCartOnButtonEvent: function (product_id) { 372 if(!getOptions().dynamicEvents.woo_add_to_cart_on_button_click.hasOwnProperty(this.tag())) 373 return; 374 375 if (window.pysWooProductData.hasOwnProperty(product_id)) { 376 if (window.pysWooProductData[product_id].hasOwnProperty('pinterest')) { 377 378 var event = getUtils().clone(getOptions().dynamicEvents.woo_add_to_cart_on_button_click[this.tag()]); 379 getUtils().copyProperties(window.pysWooProductData[product_id]['pinterest'].params, event.params); 380 this.fireEvent(event.name, event); 381 382 } 383 } 384 385 }, 386 387 onWooAddToCartOnSingleEvent: function (product_id, qty, product_type, is_external, $form) { 388 389 window.pys_woo_product_data = window.pys_woo_product_data || []; 390 391 if(!getOptions().dynamicEvents.woo_add_to_cart_on_button_click.hasOwnProperty(this.tag())) 392 return; 393 394 395 if (product_type === getUtils().PRODUCT_VARIABLE && !getOptions().pinterest.wooVariableAsSimple) { 396 product_id = parseInt($form.find('input[name="variation_id"]').val()); 397 } 398 399 if (window.pysWooProductData.hasOwnProperty(product_id)) { 400 if (window.pysWooProductData[product_id].hasOwnProperty('pinterest')) { 401 402 var event = getUtils().clone(getOptions().dynamicEvents.woo_add_to_cart_on_button_click[this.tag()]) 403 getUtils().copyProperties(window.pysWooProductData[product_id]['pinterest'].params, event.params); 404 405 if(product_type === getUtils().PRODUCT_GROUPED ) { 406 var total = 0; 407 $form.find(".woocommerce-grouped-product-list .qty").each(function(index){ 408 var childId = $(this).attr('name').replaceAll("quantity[","").replaceAll("]",""); 409 var quantity = parseInt($(this).val()); 410 if(isNaN(quantity)) { 411 quantity = 0; 412 } 413 var price = window.pysWooProductData[product_id]['pinterest'].grouped[childId].price; 414 total += price * quantity; 415 }); 416 if(total == 0) return;// skip if no items selected 417 if(getOptions().woo.addToCartOnButtonValueEnabled && 418 getOptions().woo.addToCartOnButtonValueOption !== 'global') { 419 event.params.value = total; 420 } 421 } else { 422 // maybe customize value option 423 if (getOptions().woo.addToCartOnButtonValueEnabled && 424 getOptions().woo.addToCartOnButtonValueOption !== 'global') { 425 event.params.value = event.params.value * qty; 426 } 427 } 428 event.params.product_quantity = qty; 429 430 431 if(product_type === getUtils().PRODUCT_BUNDLE) { 432 var data = $(".bundle_form .bundle_data").data("bundle_form_data"); 433 var items_sum = getBundlePriceOnSingleProduct(data); 434 var price = (data.base_price+items_sum )* qty; 435 if (getOptions().woo.addToCartOnButtonValueEnabled && getOptions().woo.addToCartOnButtonValueOption !== 'global') { 436 event.params.value = price; 437 } 438 } 439 440 var event_name = is_external ? getOptions().woo.affiliateEventName : event.name; 441 442 this.fireEvent(event_name, event); 443 } 444 } 445 }, 446 447 onWooRemoveFromCartEvent: function (event) { 448 this.fireEvent(event.name, event); 449 }, 450 451 onWooAffiliateEvent: function (product_id) { 452 if(!getOptions().dynamicEvents.woo_affiliate.hasOwnProperty(this.tag())) 453 return; 454 var event = getOptions().dynamicEvents.woo_affiliate[this.tag()]; 455 456 if (window.pysWooProductData.hasOwnProperty(product_id)) { 457 if (window.pysWooProductData[product_id].hasOwnProperty('pinterest')) { 458 459 event = getUtils().copyProperties(event, {}) 460 getUtils().copyProperties(window.pysWooProductData[product_id][this.tag()].params, event.params) 461 this.fireEvent( getOptions().woo.affiliateEventName, event); 462 463 } 464 } 465 }, 466 467 onWooPayPalEvent: function (event) { 468 this.fireEvent(event.name, event); 469 }, 470 471 onEddAddToCartOnButtonEvent: function (download_id, price_index, qty) { 472 if(!getOptions().dynamicEvents.edd_add_to_cart_on_button_click.hasOwnProperty(this.tag())) 473 return; 474 var event = getOptions().dynamicEvents.edd_add_to_cart_on_button_click[this.tag()]; 475 476 if (window.pysEddProductData && window.pysEddProductData.hasOwnProperty(download_id)) { 477 478 var index; 479 480 if (price_index) { 481 index = download_id + '_' + price_index; 482 } else { 483 index = download_id; 484 } 485 486 if (window.pysEddProductData && window.pysEddProductData[download_id].hasOwnProperty(index)) { 487 if (window.pysEddProductData && window.pysEddProductData[download_id][index].hasOwnProperty('pinterest')) { 488 489 event = getUtils().copyProperties(event, {}) 490 getUtils().copyProperties(window.pysEddProductData[download_id][index]['pinterest'].params, event.params); 491 492 // maybe customize value option 493 if (getOptions().edd.addToCartOnButtonValueEnabled && getOptions().edd.addToCartOnButtonValueOption !== 'global') { 494 event.params.value = event.params.value * qty; 495 } 496 497 event.params.product_quantity = qty; 498 this.fireEvent(event.name,event); 499 } 500 } 501 } 502 }, 503 504 onEddRemoveFromCartEvent: function (event) { 505 this.fireEvent(event.name, event); 506 }, 507 onPageScroll: function (event) { 508 this.fireEvent(event.name, event); 509 }, 510 onTime: function (event) { 511 this.fireEvent(event.name, event); 512 }, 513 514 }; 515 516 }(jQuery); 517
518 window.pys = window.pys || {}; 519 window.pys.Pinterest = Pinterest; 520 521}(jQuery);
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.