1(function() { 2 const ga4DirectEvents = { 3 'Add Shipping Info': 'add_shipping_info', 4 'Add Payment Info': 'add_payment_info', 5 }; 6 7 const runWhenReady = function(fn) { 8 if (document.readyState === 'complete' || document.readyState === 'interactive') 9 { 10 fn(); 11 return; 12 } 13 14 document.addEventListener('DOMContentLoaded', fn); 15 }; 16 17 const buildVariant = function(attrs) { 18 if (!attrs) 19 { 20 return ''; 21 } 22 23 const parts = Object.values(attrs).filter(Boolean).map(String); 24 25 return parts.length ? parts.join(' / ') : ''; 26 }; 27 28 const resolveQuantity = function($button) { 29 if ($button && $button.length) 30 { 31 const btnQty = parseInt($button.data('quantity'), 10); 32 33 if (!Number.isNaN(btnQty) && btnQty > 0) 34 { 35 return btnQty; 36 } 37 } 38 39 const formQty = parseInt( 40 (document.querySelector('form.cart .qty') || {}).value || '1', 41 10, 42 ); 43 44 return Number.isNaN(formQty) ? 1 : formQty; 45 }; 46 47 const parseButtonPayload = function($button) { 48 if (!$button || !$button.length) 49 { 50 return null; 51 } 52 53 const raw = $button.attr('data-zaraz-product'); 54 55 if (!raw) 56 { 57 return null; 58 } 59 60 try { 61 return JSON.parse(raw); 62 } catch (e) { 63 return null; 64 } 65 }; 66 67 const toGA4Items = function(data) { 68 const result = { 69 currency: data.currency, 70 value: data.value, 71 }; 72 73 if (data.products) 74 { 75 result.items = data.products.map(function(p) { 76 const item = { 77 item_id: p.product_id || p.sku, 78 item_name: p.name, 79 price: p.price, 80 quantity: p.quantity, 81 }; 82 83 if (p.category) { item.item_category = p.category; } 84 if (p.brand) { item.item_brand = p.brand; } 85 if (p.variant) { item.item_variant = p.variant; } 86 87 return item; 88 }); 89 } 90 91 return result; 92 }; 93 94 const init = function() { 95 if (typeof zaraz === 'undefined' || !window.zarazGA) 96 { 97 return; 98 } 99 100 const scriptData = window.zarazGA.scriptData || {}; 101 let currentVariation = null; 102 103 runWhenReady(function() { 104 const events = scriptData.events || []; 105 106 events.forEach(function(name) { 107 const info = (scriptData.data && scriptData.data[name]) || {}; 108 109 if (ga4DirectEvents[name]) 110 { 111 zaraz.track(ga4DirectEvents[name], toGA4Items(info)); 112 } else { 113 zaraz.ecommerce(name, info); 114 } 115 }); 116 117 if (!window.jQuery) 118 { 119 return; 120 } 121 122 const $ = window.jQuery; 123 124 $(document).on('found_variation', '.variations_form', function(event, variation) { 125 currentVariation = variation || null; 126 }); 127 128 $(document).on('reset_data hide_variation', '.variations_form', function() { 129 currentVariation = null; 130 }); 131 132 $(document.body).on('added_to_cart', function(event, fragments, cartHash, $button) { 133 const basePayload = parseButtonPayload($button) || scriptData.productData; 134 135 if (!basePayload) 136 { 137 return; 138 } 139 140 const payload = Object.assign({}, basePayload, { 141 quantity: resolveQuantity($button), 142 }); 143 144 if (scriptData.productData && currentVariation) 145 { 146 if (typeof currentVariation.display_price !== 'undefined') 147 { 148 payload.price = Number(currentVariation.display_price); 149 } 150 151 if (currentVariation.sku) 152 { 153 payload.sku = currentVariation.sku; 154 } 155 156 const variant = buildVariant(currentVariation.attributes); 157 158 if (variant) 159 { 160 payload.variant = variant; 161 } 162 } 163 164 zaraz.ecommerce('Product Added', payload); 165 }); 166 }); 167 }; 168 169 if (typeof module !== 'undefined' && module.exports) 170 { 171 module.exports = { toGA4Items, buildVariant, resolveQuantity, parseButtonPayload, ga4DirectEvents, init }; 172 } else { 173 init(); 174 } 175})();
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.