1// Send events to GA4 2// ===== Send GA4 Events ===== 3 4// Send GA4 event generic call 5function sendGA4Event(eventName, eventParams = {}) { 6 if (!window.dataLayer) { 7 window.dataLayer = []; 8 } 9 window.dataLayer.push({ 10 event: eventName, 11 ...eventParams 12 }); 13} 14 15// "Remove From Cart" event in sidecart 16function ga4SendRemoveFromCartEvent(sku, deletedProduct) { 17 const ecommerceObj = removeFromMinicartObj(deletedProduct); 18 19 dataLayer.push({ ecommerce: null }); 20 dataLayer.push({ 21 event: 'remove_from_cart_mini', 22 ecommerce: ecommerceObj 23 }); 24} 25 26// "Add To Cart Quickview" event in Sam's dynamic carousels 27function ga4SendSamDynamicCarouselATCEvent(eventName) { 28 dataLayer.push({ ecommerce: null }); 29 dataLayer.push({ 30 event: eventName || 'view_qv', 31 }); 32} 33 34// "View Minicart" event in header 35function ga4SendViewMiniCartEvent(eventName) { 36 dataLayer.push({ ecommerce: null }); 37 dataLayer.push({ 38 event: eventName || 'view_mini_cart', 39 }); 40} 41 42// ===== End Send GA4 Events ===== 43 44 45function removeFromMinicartObj(cartItem) { 46 const imageURL = cartItem[0]; 47 const description = cartItem[1]; 48 const optionsHTML = cartItem[2]; 49 const stockMessage = cartItem[3]; 50 const vas = cartItem[4]; 51 const price = cartItem[5]; 52 const extendedPrice = cartItem[6]; 53 const cdno = cartItem[7]; 54 const quantity = cartItem[8]; 55 const subtotal = cartItem[9]; 56 const customizationFee = cartItem[10]; 57 const itemTotal = cartItem[11]; 58 const itemID = cartItem[12]; 59 const errorMessage = cartItem[13]; 60 const locationID = cartItem[14]; 61 const cdnoRepeat = cartItem[15]; 62 const itemType = cartItem[16]; 63 64 // Options 65 function getProductOptions(optionsHTML) { 66 const tempDiv = document.createElement('div'); 67 tempDiv.innerHTML = optionsHTML; 68 const listItems = tempDiv.querySelectorAll('li'); 69 70 return { 71 option1: listItems[0]?.textContent.trim() || '', 72 option2: listItems[1]?.textContent.trim() || '', 73 option3: listItems[2]?.textContent.trim() || '' 74 }; 75 } 76 77 const { option1, option2, option3 } = getProductOptions(optionsHTML); 78 79 // Price 80 function getPriceValues(priceHTML) { 81 const tempDiv = document.createElement('div'); 82 tempDiv.innerHTML = priceHTML; 83 84 const original = tempDiv.querySelector('.original')?.textContent.replace('$', '').trim() || ''; 85 const discount = tempDiv.querySelector('.discount')?.textContent.replace('$', '').trim() || ''; 86 const strong = tempDiv.querySelector('strong')?.textContent.replace('$', '').trim() || ''; 87 88 return { 89 originalPrice: original || strong, 90 discountPrice: discount 91 }; 92 } 93 94 const { originalPrice, discountPrice } = getPriceValues(price); 95 96 return { 97 currency: "USD", 98 value: "", 99 items: [ 100 { 101 item_id: `${itemID}`, 102 item_name: description.replace(/"/g, '"'), 103 affiliation: "Galls Website", 104 item_variant1: option1, 105 item_variant2: option2, 106 item_variant3: option3, 107 location_id: locationID, 108 price: parseFloat(originalPrice), 109 discountPrice: parseFloat(discountPrice), 110 customizationFee: parseFloat(customizationFee) || '', 111 quantity: parseInt(quantity, 10) 112 } 113 ] 114 }; 115} 116 117// "Sponsored Ads View/Click" event for PLP grid banners 118function ga4SendSponsoredAdEvent(adData, eventType = 'view') { 119 const eventName = eventType === 'view' ? 'view' : 'click'; 120 121 const ecommerceObj = { 122 ad_id: adData.ad_id || '', 123 template: adData.template || '', 124 type: adData.type || 'grid_banner', 125 url: adData.url || '', 126 description: adData.description || '', 127 row: adData.rowNum ? String(adData.rowNum) : '', 128 start_date: adData.start_date || '', 129 start_time: adData.start_time || '', 130 target_url: adData.buttonLink || adData.product || '', 131 sponsor: adData.sponsor || '' 132 }; 133 134 dataLayer.push({ ecommerce: null });
135 dataLayer.push({ 136 event: eventName, 137 ecommerce: ecommerceObj 138 }); 139} 140 141/* === Listen for Sponsored Ad Events === */ 142document.addEventListener('sponsoredAdView', function(e) { 143 ga4SendSponsoredAdEvent(e.detail, 'view'); 144}); 145 146document.addEventListener('sponsoredAdClick', function(e) { 147 ga4SendSponsoredAdEvent(e.detail, 'click'); 148}); 149/* === End Sponsored Ad Events === */ 150 151// web-999 stage only 152/* === PDP Promo Bar Events === */ 153function ga4SendPromoBarEvent(adData, eventType = 'view') { 154 const eventName = eventType === 'view' ? 'view' : 'click'; 155 156 const ecommerceObj = { 157 ad_id: adData.ad_id || '', 158 template: 'pdp', 159 type: 'promo_bar', 160 url: adData.cta_link || '', 161 description: adData.primary_text || '', 162 start_date: adData.start_date || '', 163 end_date: adData.end_date || '', 164 priority_rank: adData.priority_rank || 0, 165 product_slug: adData.product_slug || '', 166 sponsor_brand: adData.sponsor_brand || '', 167 sponsored: adData.is_sponsored || false 168 }; 169 170 dataLayer.push({ ecommerce: null }); 171 dataLayer.push({ 172 event: eventName, 173 ecommerce: ecommerceObj 174 }); 175} 176 177document.addEventListener('promoBarView', function(e) { 178 ga4SendPromoBarEvent(e.detail, 'view'); 179}); 180 181document.addEventListener('promoBarClick', function(e) { 182 ga4SendPromoBarEvent(e.detail, 'click'); 183}); 184/* === End PDP Promo Bar Events === */
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.