1(function (window, document) { 2 'use strict'; 3 4 var ready = false; 5 var pending = []; 6 7 function storageGet(store, key) { 8 try { 9 return store.getItem(key); 10 } catch (e) { 11 return null; 12 } 13 } 14 15 function storageSet(store, key, value) { 16 try { 17 store.setItem(key, value); 18 } catch (e) { 19 // Measurement must never interrupt the shopping flow. 20 } 21 } 22 23 function sendNow(eventName, params, options) { 24 options = options || {}; 25 params = params || {}; 26 27 if (!eventName || typeof window.gtag !== 'function') { 28 return; 29 } 30 31 if (eventName === 'purchase' && params.transaction_id) { 32 var purchaseKey = 'ahm_ga4_purchase_' + String(params.transaction_id); 33 if (storageGet(window.localStorage, purchaseKey)) { 34 return; 35 } 36 storageSet(window.localStorage, purchaseKey, '1'); 37 } 38 39 window.gtag('event', eventName, params); 40 41 if (eventName === 'purchase' && options.ads_send_to) { 42 window.gtag('config', 'AW-11493962788'); 43 window.gtag('event', 'conversion', { 44 send_to: options.ads_send_to, 45 value: Number(params.value || 0), 46 currency: params.currency || 'TRY', 47 transaction_id: String(params.transaction_id || '') 48 }); 49 } 50 51 window.__AHMEGON_GA4_LAST_EVENT__ = { 52 event: eventName, 53 params: params, 54 sent_at: new Date().toISOString() 55 }; 56 57 // Non-sensitive QA marker: makes the last emitted event observable from 58 // automated browser checks without exposing customer or order data. 59 document.documentElement.setAttribute('data-ahm-ga4-last-event', eventName); 60 if (params.transaction_id) { 61 document.documentElement.setAttribute('data-ahm-ga4-last-transaction', String(params.transaction_id)); 62 } 63 } 64 65 function send(eventName, params, options) { 66 if (!ready) { 67 pending.push([eventName, params, options]); 68 return; 69 } 70 sendNow(eventName, params, options); 71 } 72 73 function flush() { 74 ready = true; 75 while (pending.length) { 76 var eventData = pending.shift(); 77 sendNow(eventData[0], eventData[1], eventData[2]); 78 } 79 } 80 81 function pageEvent() { 82 var config = window.AHMEGON_GA4_PAGE; 83 84 if (!config && window._QuickCheckoutData && window._QuickCheckoutData.ahmegon_ga4) { 85 config = window._QuickCheckoutData.ahmegon_ga4; 86 } 87 88 if (config && config.event && config.params) { 89 send(config.event, config.params, config); 90 } 91 } 92 93 function ecommerceContext() { 94 var config = window.AHMEGON_GA4_PAGE; 95 96 if (!config && window._QuickCheckoutData && window._QuickCheckoutData.ahmegon_ga4) { 97 config = window._QuickCheckoutData.ahmegon_ga4; 98 } 99 100 return config && config.params ? config.params : {}; 101 } 102 103 function checkoutContextKey(context) { 104 var items = context.items || []; 105 var itemKey = items.map(function (item) { 106 return String(item.item_id || '') + ':' + String(item.quantity || 1); 107 }).join(','); 108 109 return [ 110 String(context.currency || 'TRY'), 111 String(Number(context.value || 0).toFixed(2)), 112 itemKey 113 ].join('|'); 114 } 115 116 function sendCheckoutSelection(target) { 117 var eventName = ''; 118 var detailName = ''; 119 var detailValue = ''; 120 121 if (!target || !target.name || !target.checked) { 122 return; 123 } 124 125 if (target.name === 'shipping_method') { 126 eventName = 'add_shipping_info'; 127 detailName = 'shipping_tier'; 128 detailValue = target.value || ''; 129 } else if (target.name === 'payment_method') { 130 eventName = 'add_payment_info'; 131 detailName = 'payment_type'; 132 detailValue = target.value || ''; 133 } else { 134 return; 135 } 136 137 var context = ecommerceContext(); 138 var key = 'ahm_ga4_' + eventName + '_' + detailValue + '_' + checkoutContextKey(context); 139 140 if (storageGet(window.sessionStorage, key)) { 141 return; 142 } 143 144 storageSet(window.sessionStorage, key, '1'); 145 146 var params = { 147 currency: context.currency || 'TRY', 148 value: Number(context.value || 0), 149 items: context.items || [] 150 }; 151 params[detailName] = detailValue; 152 send(eventName, params); 153 } 154 155 function sendInitialCheckoutSelections() { 156 var selected = document.querySelectorAll( 157 'input[name="shipping_method"]:checked, input[name="payment_method"]:checked' 158 ); 159 160 Array.prototype.forEach.call(selected, sendCheckoutSelection); 161 } 162 163 function checkoutSelections() { 164 document.addEventListener('change', function (event) { 165 var target = event.target; 166 167 window.setTimeout(function () { 168 sendCheckoutSelection(target); 169 }, 650); 170 }, true); 171 172 // Journal selects the first available shipping and payment methods while 173 // rendering the checkout. Those defaults do not emit a native change event, 174 // so record them once after the Vue checkout has finished mounting. 175 window.setTimeout(sendInitialCheckoutSelections, 1200); 176 177 var selectionPolls = 0; 178 var selectionTimer = window.setInterval(function () { 179 selectionPolls += 1; 180 sendInitialCheckoutSelections(); 181 182 if (document.querySelector('input[name="shipping_method"]:checked') && 183 document.querySelector('input[name="payment_method"]:checked')) { 184 window.clearInterval(selectionTimer); 185 } else if (selectionPolls >= 20) { 186 window.clearInterval(selectionTimer); 187 } 188 }, 500); 189 } 190 191 function ajaxEvents() { 192 if (!window.jQuery) { 193 return; 194 } 195 196 window.jQuery(document).ajaxSuccess(function (event, xhr, settings, response) { 197 var url = settings && settings.url ? String(settings.url) : ''; 198 199 if (url.indexOf('journal3/checkout') !== -1) { 200 window.setTimeout(sendInitialCheckoutSelections, 800); 201 } 202 203 if (url.indexOf('checkout/cart/add') === -1) { 204 return; 205 } 206 207 var json = response; 208 if (typeof json === 'string') { 209 try { 210 json = JSON.parse(json); 211 } catch (e) { 212 return; 213 } 214 } 215 216 if (json && json.ahmegon_ga4 && json.ahmegon_ga4.params) { 217 send('add_to_cart', json.ahmegon_ga4.params); 218 } 219 }); 220 } 221 222 window.AhmegonGA4 = { 223 send: send 224 }; 225 226 function initialize() { 227 flush(); 228 pageEvent(); 229 checkoutSelections(); 230 ajaxEvents(); 231 } 232 233 if (document.readyState === 'loading') { 234 document.addEventListener('DOMContentLoaded', initialize, { once: true }); 235 } else { 236 initialize(); 237 } 238})(window, document);
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.