1// WOO EVENTS 2/* <fs_premium_only> */ 3 4FP.fns.generateUUID = async function ( string ) { 5 6 // generate SHA 256 7 const encoder = new TextEncoder(); 8 const data = encoder.encode(string); 9 const hashBuffer = await crypto.subtle.digest('SHA-256', data); 10 const hashArray = Array.from(new Uint8Array(hashBuffer)); 11 fpdata.user.UUID = hashArray.map(b => b.toString(16).padStart(2, '0')).join(''); 12 FP.setCookie('fp_uuid', fpdata.user.UUID, 365 ); 13 localStorage.setItem('fp_uuid', fpdata.user.UUID ); 14} 15/* </fs_premium_only> */ 16 17function fupi_fbp_footer_woo(){ 18 19 // TRACK IMPRESSIONS 20 21 function track_woo_impress() { 22 23 if ( ! fpdata.woo.lists.single ) return; 24 if ( ! fp.woo.fbp ) fp.woo.fbp = { 'single' : [] }; 25 26 let items_a = [], 27 value = 0, 28 is_variable_prod = false, 29 item_ids = fpdata.woo.lists.single.filter( id => ! fp.woo.fbp.single.includes(id) ); // track only items that were not tracked before 30 31 item_ids.forEach( id => { 32 33 let prod = fpdata.woo.products[id]; 34 35 if ( prod ) { 36 37 let item = { 38 'id' : FP.fns.get_woo_prod_id(prod), 39 'quantity' : 1, 40 }; 41 42 if ( prod.type == 'variable' ) is_variable_prod = true; 43 44 value += prod.price; 45 items_a.push( item ); 46 } 47 } ); 48 49 // prevent double tracking in case the next prods are added dynamically 50 fp.woo.fbp.single.push(...item_ids); 51 52 if ( items_a.length > 0 ) { 53 54 let track_var_as_single = fp.woo.variable_tracking_method == 'track_parents', 55 content_type = items_a.length == 1 && is_variable_prod && ! track_var_as_single ? 'product_group' : 'product'; 56 57 let payload_o = { 58 'contents' : items_a, 59 'currency' : fpdata.woo.currency, 60 'value' : value, 61 'content_type' : content_type, 62 }; 63 64 FP.track_fbp_evt( false, 'ViewContent', false, payload_o ); 65 } 66 }; 67 68 if ( ! ( fp.woo.dont_track_views_after_refresh && fpdata.refreshed ) ){ 69 track_woo_impress(); 70 FP.addAction( ['woo_impress'], track_woo_impress ); 71 } 72 73 // TRACK DEFAULT VARIANT VIEW 74 // TRACK VARIANT VIEWS 75 76 function woo_variant_view( variant_id ){ 77 78 let prod = fpdata.woo.products[variant_id]; 79 80 let payload_o = { 81 'contents' : [ { 82 'id' : FP.fns.get_woo_prod_id(prod), 83 'quantity' : 1, 84 } ], 85 'currency' : fpdata.woo.currency, 86 'value' : prod.price, 87 'content_type' : 'product' 88 }; 89 90 FP.track_fbp_evt( false, 'ViewContent', false, payload_o ); 91 } 92 93 FP.addAction( ['woo_variant_view'], woo_variant_view ); 94 FP.addAction( ['woo_def_variant_view'], woo_variant_view ); 95 96 // TRACK ADD TO CART 97 // TRACK ADD TO WISHLIST 98 99 function track_items( data, event_name ){ 100 101 let products_data = data.products, 102 event_value = data.value, 103 items_a = []; 104 105 products_data.forEach( prod_a => { 106 107 let prod = prod_a[0], 108 qty = prod_a[1] || prod.qty || 1, 109 item = { 110 'id' : FP.fns.get_woo_prod_id( prod ), 111 'item_price' : prod.price, 112 'quantity' : parseInt(qty), 113 }; 114 115 items_a.push( item ); 116 } ); 117 118 if ( items_a.length == 0 ) return false; 119 120 let payload_o = { 121 'contents' : items_a, 122 'value' : event_value, 123 'currency' : fpdata.woo.currency, 124 'content_type' : 'product' 125 }; 126 127 FP.track_fbp_evt( false, event_name, false, payload_o ); 128 }; 129 130 FP.addAction( ['woo_add_to_cart'], data =>{ 131 track_items( data, 'AddToCart' ); 132 } ); 133 134 if ( fp.woo.cart_to_track ) track_items( fp.woo.cart_to_track, 'AddToCart' ); // when ATC is tracked in cart 135 136 FP.addAction( ['woo_add_to_wishlist'], data => { 137 track_items( data, 'AddToWishlist'); 138 } ); 139 140 // TRACK CHECKOUT 141 // TRACK ORDER 142 143 function track_cart( type ){ // type can be either "checkout" or "order" 144 145 let items_type = fp.woo.variable_tracking_method == 'track_parents' ? 'joined_items' : 'items', 146 items_a = [], 147 cart = type == 'checkout' ? fpdata.woo.cart : fpdata.woo.order, 148 event_name = type == 'checkout' ? 'InitiateCheckout' : 'Purchase'; 149 150 for ( const id in cart[items_type] ) { 151 152 let prod = cart[items_type][id], 153 item = { 154 'id' : FP.fns.get_woo_prod_id(prod), 155 'item_price' : prod.price, 156 'quantity' : prod.qty, 157 }; 158 159 items_a.push( item ); 160 } 161 162 if ( items_a.length == 0 ) return false; 163 164 let payload_o = { 165 'contents' : items_a, 166 'value' : cart.value, 167 'num_items': items_a.length, 168 'currency' : fpdata.woo.currency, 169 'content_type' : 'product', 170 }; 171 172 FP.track_fbp_evt( false, event_name, false, payload_o ); 173 } 174 175 // track order 176 // unless we already do it through server with advanced order tracking 177 if ( fp.woo.order_data_ready ) { 178 if ( ! fp.main.is_pro || ! ( fp.fbp.server_side && fp.fbp.adv_orders ) ) { 179 track_cart('order'); 180 } else { 181 if ( fp.main.debug ) console.log( '[FP] Meta Pixel purchase event is tracked by the server-side script' ); 182 } 183 }; 184 185 // track the start of checkout (except when the whole page or its part is refreshed) 186 if ( ! fpdata.refreshed ) { 187 if ( fp.woo.checkout_data_ready ) { 188 fp.fbp.woo_checkout_tracked = true; 189 track_cart('checkout') 190 } else { 191 document.addEventListener( 'fupi_woo_checkout_data_ready', ()=>{ 192 if ( ! fp.fbp.woo_checkout_tracked ) { 193 fp.fbp.woo_checkout_tracked = true; 194 track_cart('checkout'); 195 } 196 }) 197 }; 198 } 199 200 FP.loaded('fbp_footer_woo'); 201}; 202 203// STANDARD EVENTS 204 205function fupi_fbp_footer(){ 206 207 // TRACK OUTBOUND LINKS 208 209 if ( fp.fbp.track_outbound ) { 210 FP.addAction( ['click'], function(){ 211 if ( fpdata.clicked.link && fpdata.clicked.link.is_outbound ) { 212 var data = { 213 'url' : fpdata.clicked.link.href, 214 'time on page' : fpdata.activity.total, 215 }; 216 FP.track_fbp_evt( true, 'outbound', false, data, !! fp.fbp.track_outbound_capi ); 217 } 218 } ); 219 } 220 221 // TRACK CLICKS ON EMAIL & TEL LINKS 222 223 if ( fp.fbp.track_email_tel ) { 224 FP.addAction( ['click'], function(){ 225 if ( fpdata.clicked.link && ( fpdata.clicked.link.is_email || fpdata.clicked.link.is_tel ) ) { 226 var data = { 227 'target' : fpdata.clicked.link.safe_email || fpdata.clicked.link.safe_tel, 228 'type' : fpdata.clicked.link.is_email ? 'email' : 'tel', 229 'time on page' : fpdata.activity.total, 230 }; 231 FP.track_fbp_evt( true, 'Contact', false, data, !! fp.fbp.track_email_tel_capi ); 232 } 233 } ); 234 } 235 236 // TRACK AFFILIATE LINKS 237 238 if ( fp.fbp.track_affiliate ) { 239 FP.addAction( ['click'], function(){ 240 var trackedAffLink = FP.getTrackedAffiliateLink( fp.fbp.track_affiliate ); 241 if ( trackedAffLink ) { 242 var data = { 243 'target' : trackedAffLink, 244 'time on page' : fpdata.activity.total, 245 }; 246 FP.track_fbp_evt( true, 'affiliate', false, data, !! fp.fbp.track_affiliate_capi ); 247 } 248 } ); 249 } 250 251 // TRACK FILE DOWNLOADS 252 253 if ( fp.fbp.track_file_downl ) { 254 FP.addAction( ['click'], function(){ 255 var filename = FP.getTrackedFilename( fp.fbp.track_file_downl ); 256 if ( filename ) { 257 var data = { 258 'file' : filename, 259 'time on page' : fpdata.activity.total, 260 }; 261 FP.track_fbp_evt( true, 'file download', false, data, !! fp.fbp.track_file_downl_capi ); 262 } 263 } ); 264 }; 265 266 // TRACK FORMS 267 268 if ( fp.fbp.track_forms ) { 269 FP.addAction( ['form_submit'], function(){ 270 var submittedForm = FP.getSubmittedForm( fp.fbp.track_forms ); 271 if ( submittedForm ){ 272 var data = { 273 'form' : submittedForm, 274 'time on page' : fpdata.activity.total, 275 }; 276 FP.track_fbp_evt( true, 'form submit', false, data, !! fp.fbp.track_forms_capi ); 277 } 278 }) 279 } 280 281 // TRACK SCROLLS 282 283 if ( fp.fbp.track_scroll ){ 284 fp.fbp.track_scroll = FP.formatScrollPoints( fp.fbp.track_scroll ); 285 FP.addAction( ['scroll', 'active_time_tick'], function(){ 286 // check if the window was scrolled 287 if ( fp.fbp.track_scroll.length > 0 && fpdata.activity.total >= fp.track.track_scroll_time && fpdata.scrolled.current_px >= fp.track.track_scroll_min ) { 288 var reachedPoint = FP.isScrollTracked( fp.fbp.track_scroll ); 289 if ( reachedPoint ) { 290 // remove from array the scroll points that were already reached 291 fp.fbp.track_scroll = fp.fbp.track_scroll.filter( function( point ){ return point > reachedPoint } ); 292 // track scroll 293 var data = { 294 'scroll height' : reachedPoint, 295 'time on page' : fpdata.activity.total, 296 }; 297 FP.track_fbp_evt( true, 'scroll', false, data, !! fp.fbp.track_scroll_capi ); 298 } 299 } 300 } ); 301 } 302 303 // TRACK VIEWS OF ELEMENTS 304 // for performance: waits 250ms for dynamically generated content to finish 305 306 FP.fns.fbp_observe_inters = ( newly_added_els = false ) => { 307 308 let send_el_view_evt = el => { 309 310 var data = { 311 'element' : el.dataset['fbp_view'], 312 'el' : el.dataset['fbp_view'], // for compat. with FP ver < 2.3 313 'time on page' : fpdata.activity.total, 314 }; 315 FP.track_fbp_evt( true, 'user viewed', false, data, !! fp.fbp.track_views_capi ); 316 }; 317 318 FP.intersectionObserver( newly_added_els, fp.fbp.track_views, 'fbp', send_el_view_evt, true); 319 } 320 321 if ( fp.fbp.track_views ) setTimeout( ()=>{ 322 FP.fns.fbp_observe_inters(); 323 FP.addAction( ['dom_modified'], FP.fns.fbp_observe_inters ); 324 }, 250 ); 325 326 /* <fs_premium_only> */ 327 if ( fp.main.is_pro ) { 328 // TRACK USER ENGAGEMENT TIME 329 // sends total 330 331 if ( fp.fbp.track_engagement ) { 332 FP.addAction( ['page_in_blur'], function(){ 333 var data = { 'seconds' : fpdata.activity.total, }; 334 FP.track_fbp_evt( true, 'user engagement time', false, data, !! fp.fbp.track_engagement_capi ); 335 } ) 336 }; 337 338 // MAKE UUID FROM EMAIL 339 // ! saved in fupi.track 340 341 if ( fp.fbp.user_email_fields && ! fpdata?.user?.UUID ) { 342 FP.addAction( ['form_field_blur'], ()=>{ 343 if ( ! fpdata.user.UUID && fpdata.last_form_field.matches( fp.fbp.user_email_fields ) ) { 344 // check if we have an email 345 if ( fpdata.last_form_field.value && fpdata.last_form_field.value.length > 0 ) { 346 let value_str = fpdata.last_form_field.value.trim(); 347 if ( /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test( value_str ) ) { 348 value_str = 'fp' + value_str.replace('@',''); 349 value_str = value_str.toLowerCase(); 350 FP.fns.generateUUID( value_str ); 351 }; 352 } 353 } 354 } ) 355 } 356 } 357 358 /* </fs_premium_only> */ 359 360 // TRACK SPECIFIC ELEMENTS 361 362 if ( fp.fbp.track_elems ) { 363 FP.addAction( ['click'], function(){ 364 var trackedElName = FP.getClickTarget( fp.fbp.track_elems ); 365 if ( trackedElName ) { 366 var data = { 367 'name' : trackedElName, 368 'time on page' : fpdata.activity.total, 369 }; 370 FP.track_fbp_evt( true, 'click on element', false, data, !! fp.fbp.track_elems_capi ); 371 } 372 }) 373 } 374 375 FP.loaded('fbp_footer'); 376};
377 378FP.load('fbp_footer', 'fupi_fbp_footer', ['fbp', 'footer_helpers']); 379FP.load('fbp_footer_woo', 'fupi_fbp_footer_woo', ['fbp', 'footer_helpers','woo']);
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.