1(function () { 2 window.dataLayer = window.dataLayer || []; 3 4 function getRecurringMeta(frequencyRaw, noOfDays) { 5 if (!frequencyRaw) return { label: "", multiplier: 1 }; 6 var freq = frequencyRaw.toString().toLowerCase(); 7 if (freq.indexOf('week') !== -1) return { label: "week", multiplier: 52 }; 8 if (freq.indexOf('month') !== -1) return { label: "month", multiplier: 12 }; 9 if (freq.indexOf('year') !== -1) return { label: "year", multiplier: 1 }; 10 if (freq.indexOf('day') !== -1) { 11 var days = parseInt(noOfDays, 10); 12 return { label: "day", multiplier: (days > 0) ? days : 1 }; 13 } 14 return { label: freq, multiplier: 1 }; 15 } 16 17 function mapGaoItems(items) { 18 return items.map(function (item) { 19 var isRecurring = !!item.recurring; 20 var meta = isRecurring ? getRecurringMeta(item.frequency, item.RecurringNoOfDays) : { label: "", multiplier: 1 }; 21 var projectedPrice = parseFloat(item.price) * meta.multiplier; 22 23 var mapped = { 24 item_name: item.item_name, 25 item_id: item.item_id, 26 price: projectedPrice, 27 quantity: item.quantity, 28 item_category: item.item_category, 29 item_brand: item.item_brand, 30 item_variant: item.item_variant, 31 recurring: isRecurring ? "true" : "false", 32 donation_type: isRecurring ? "recurring" : "one_off" 33 }; 34 35 if (isRecurring && meta.label) { 36 mapped.recurring_every = meta.label; 37 } 38 39 return mapped; 40 }); 41 } 42 43 function sumProjectedValue(mappedItems) { 44 return mappedItems.reduce(function (total, item) { 45 return total + (parseFloat(item.price) * parseInt(item.quantity, 10)); 46 }, 0); 47 } 48 49 window.pushAddToCartGA4 = function (project, type, amount, quantity, isRecurring, frequency, noOfDays) { 50 const pageType = window.location.href.includes('/project/') ? "donation_project" : "general_donation"; 51 const projectParts = project.split('_'); 52 const itemId = projectParts[0] || "unknown"; 53 const itemName = projectParts[1] ? projectParts[1].replaceAll('-', ' ') : "Donation"; 54 55 const cleanCategory = type.includes('_') ? type.split('_')[1] : type; 56 const donationType = isRecurring ? "recurring" : "one_off"; 57 58 const singleInstalmentValue = parseFloat(amount * quantity); 59 const meta = isRecurring ? getRecurringMeta(frequency, noOfDays) : { label: "", multiplier: 1 }; 60 const projectedValue = singleInstalmentValue * meta.multiplier; 61 62 const item = { 63 item_id: itemId, 64 item_name: itemName, 65 item_category: cleanCategory, 66 item_brand: "MAA International", 67 price: parseFloat(amount) * meta.multiplier, 68 quantity: parseInt(quantity), 69 recurring: isRecurring ? "true" : "false", 70 donation_type: donationType 71 }; 72 73 if (isRecurring && meta.label) { 74 item.recurring_every = meta.label; 75 } 76 77 window.dataLayer.push({ ecommerce: null }); 78 window.dataLayer.push({ 79 event: "add_to_cart", 80 ecommerce: { 81 value: projectedValue, 82 currency: "AUD", 83 ecom_pagetype: pageType, 84 items: [item] 85 } 86 }); 87 console.log("GA4: add_to_cart event pushed for " + itemName); 88 }; 89 90 // --- 1. HANDLE VIEW CART --- 91 if (window.view_cart) { 92 var c = window.view_cart; 93 var cartItems = mapGaoItems(c.Items); 94 95 dataLayer.push({ ecommerce: null }); // Clear previous ecommerce 96 dataLayer.push({ 97 event: "view_cart", 98 ecommerce: { 99 value: sumProjectedValue(cartItems), 100 currency: c.Currency, 101 ecom_pagetype: "view_cart", 102 items: cartItems 103 }, 104 recurring: cartItems.some(x => x.recurring === "true") ? "true" : "false" 105 }); 106 console.log("GA4: view_cart event detected and pushed."); 107 } 108 109 window.pushRemoveFromCartGA4 = function (item) { 110 if (!item) return; 111 112 const isRecurring = item.recurring === true || item.recurring === "true"; 113 const meta = isRecurring ? getRecurringMeta(item.frequency, item.RecurringNoOfDays) : { label: "", multiplier: 1 }; 114 115 window.dataLayer = window.dataLayer || []; 116 window.dataLayer.push({ ecommerce: null });
117 window.dataLayer.push({ 118 event: "remove_from_cart", 119 ecommerce: { 120 value: parseFloat(item.price * (item.unit || 1)) * meta.multiplier, 121 currency: "AUD", 122 ecom_pagetype: "cart", 123 items: [{ 124 item_id: item.id, 125 item_name: item.name, 126 item_category: item.category, 127 item_brand: "MAA International", 128 price: parseFloat(item.price) * meta.multiplier, 129 quantity: parseInt(item.unit || 1), 130 recurring: isRecurring ? "true" : "false", 131 donation_type: isRecurring ? "recurring" : "one_off", 132 ...(isRecurring && meta.label ? { recurring_every: meta.label } : {}) 133 }] 134 } 135 }); 136 console.log("GA4: remove_from_cart fired for", item.name); 137 }; 138 139 140 // Begin Checkout GA4 Function. 141 window.pushBeginCheckoutGA4 = function (data) { 142 if (!data) return; 143 144 var ga4Items = []; 145 var donationTypes = []; 146 var isRecurring_Fee = false; 147 148 // 1. Map the donation items 149 data.items.forEach(function (item) { 150 const isRecurring = item.recurring === true || item.recurring === "true"; 151 if (item.recurring === true || item.recurring === "true") { isRecurring_Fee = true; } 152 const meta = isRecurring ? getRecurringMeta(item.frequency, item.RecurringNoOfDays) : { label: "", multiplier: 1 }; 153 const donationType = isRecurring ? "recurring" : "one_off"; 154 155 ga4Items.push({ 156 item_id: item.item_id, 157 item_name: item.item_name, 158 item_category: item.item_category, 159 item_brand: "MAA International", 160 price: Number((parseFloat(item.price) * meta.multiplier).toFixed(2)), 161 quantity: parseInt(item.quantity), 162 recurring: isRecurring ? "true" : "false", 163 donation_type: donationType, 164 ...(isRecurring && meta.label ? { recurring_every: meta.label } : {}) 165 }); 166 167 donationTypes.push(donationType); 168 169 }); 170 171 var uniqueDonationTypes = donationTypes.filter(function (value, index, self) { 172 return self.indexOf(value) === index; 173 }); 174 175 // 2. Add Admin Fee if exists 176 if (data.onetime_admin == true || data.recurring_admin == true) { 177 ga4Items.push({ 178 item_id: "ADMIN_FEE", 179 item_name: "Admin Fee", 180 item_category: "Fee", 181 item_brand: "MAA International", 182 price: Number(parseFloat(data.adminFee).toFixed(2)), 183 quantity: 1, 184 recurring: isRecurring_Fee, 185 donation_type: uniqueDonationTypes 186 }); 187 } 188 189 // 3. Add Card Fee if exists 190 if (data.onetime_credit == true || data.recurring_credit == true) { 191 ga4Items.push({ 192 item_id: "CARD_FEE", 193 item_name: "Card Fee", 194 item_category: "Fee", 195 item_brand: "MAA International", 196 price: Number(parseFloat(data.cardFee).toFixed(2)), 197 quantity: 1, 198 recurring: isRecurring_Fee, 199 donation_type: uniqueDonationTypes 200 }); 201 } 202 203 var projectedTotal = ga4Items.reduce(function (total, item) { 204 return total + (item.price * item.quantity); 205 }, 0); 206 207 // 4. Push to Data Layer 208 window.dataLayer = window.dataLayer || []; 209 window.dataLayer.push({ ecommerce: null }); 210 window.dataLayer.push({ 211 event: "begin_checkout", 212 ecommerce: { 213 value: Number(projectedTotal.toFixed(2)), 214 currency: "AUD", 215 ecom_pagetype: "checkout_step_1", 216 items: ga4Items, 217 donation_type: uniqueDonationTypes 218 } 219 }); 220 221 console.log("GA4: begin_checkout fired", ga4Items); 222 }; 223 224 window.pushUserLoggedInGA4 = function (data) { 225 if (!data) return; 226 227 window.dataLayer = window.dataLayer || []; 228 window.dataLayer.push({ ecommerce: null });
229 window.dataLayer.push({ 230 event: "user_logged_in", 231 user_data: data 232 }); 233 console.log("GA4: user logged in event detected and pushed."); 234 }; 235 236 //// UserLoggedIn GA4 Function: 237 //if (window.userLoggedIn) { 238 // var p = window.userLoggedIn; 239 240 241 // dataLayer.push({ ecommerce: null }); // Clear previous ecommerce 242 // dataLayer.push({ 243 // event: "user_logged_in", 244 // user_data: p.UserData 245 // }); 246 // console.log("GA4: user logged in event detected and pushed."); 247 //} 248 249 250 // Begin Add Payment Info 251 window.pushAddPaymentInfoGA4 = function (data, paymentMethod) { 252 if (!data || !data.items) return; 253 254 var ga4Items = []; 255 var donationTypes = []; 256 var isRecurring_Fee = false; 257 258 // 1. Map the donation items 259 data.items.forEach(function (item) { 260 const isRecurring = item.recurring === true || item.recurring === "true"; 261 if (item.recurring === true || item.recurring === "true") { isRecurring_Fee = true; }; 262 const meta = isRecurring ? getRecurringMeta(item.frequency, item.RecurringNoOfDays) : { label: "", multiplier: 1 }; 263 const donationType = isRecurring ? "recurring" : "one_off"; 264 265 ga4Items.push({ 266 item_id: item.item_id, 267 item_name: item.item_name, 268 item_category: item.item_category, 269 item_brand: "MAA International", 270 price: Number((parseFloat(item.price) * meta.multiplier).toFixed(2)), 271 quantity: parseInt(item.quantity), 272 recurring: isRecurring ? "true" : "false", 273 donation_type: donationType, 274 ...(isRecurring && meta.label ? { recurring_every: meta.label } : {}) 275 }); 276 277 donationTypes.push(donationType); 278 }); 279 280 var uniqueDonationTypes = donationTypes.filter(function (value, index, self) { 281 return self.indexOf(value) === index; 282 }); 283 284 // 2. Add Fees as line items 285 if (data.onetime_admin == true || data.recurring_admin == true) { 286 ga4Items.push({ 287 item_id: "ADMIN_FEE", 288 item_name: "Admin Fee", 289 item_category: "Fee", 290 item_brand: "MAA International", 291 price: Number(parseFloat(data.adminFee).toFixed(2)), 292 quantity: 1, 293 recurring: isRecurring_Fee, 294 donation_type: uniqueDonationTypes 295 }); 296 } 297 298 if (data.onetime_credit == true || data.recurring_credit == true) { 299 ga4Items.push({ 300 item_id: "CARD_FEE", 301 item_name: "Card Fee", 302 item_category: "Fee", 303 item_brand: "MAA International", 304 price: Number(parseFloat(data.cardFee).toFixed(2)), 305 quantity: 1, 306 recurring: isRecurring_Fee, 307 donation_type: uniqueDonationTypes 308 }); 309 } 310 311 var projectedTotal = ga4Items.reduce(function (total, item) { 312 return total + (item.price * item.quantity); 313 }, 0); 314 315 var uniqueDonationTypes = donationTypes.filter(function (value, index, self) { 316 return self.indexOf(value) === index; 317 }); 318 319 // 3. Push to GA4 320 window.dataLayer = window.dataLayer || []; 321 window.dataLayer.push({ ecommerce: null }); 322 window.dataLayer.push({ 323 event: "add_payment_info", 324 ecommerce: { 325 value: Number(projectedTotal.toFixed(2)), 326 currency: "AUD", 327 payment_type: paymentMethod, 328 items: ga4Items, 329 donation_type: uniqueDonationTypes 330 } 331 }); 332 }; 333 334 // --- 2. HANDLE PURCHASE --- 335 if (window.purchaseData) { 336 var p = window.purchaseData; 337 var purchaseItems = mapGaoItems(p.Items); 338 339 var includeUserData = (p.UserData && p.UserData.user_id != "65") ? true : false; 340 341 dataLayer.push({ ecommerce: null }); // Clear previous ecommerce 342 dataLayer.push({ 343 event: "purchase", 344 ecommerce: { 345 transaction_id: p.TransactionId, 346 value: sumProjectedValue(purchaseItems), 347 currency: p.Currency, 348 tax: p.Tax, 349 shipping: p.Shipping, 350 payment_type: p.PaymentType, 351 ecom_pagetype: "purchase", 352 items: purchaseItems 353 }, 354 recurring: purchaseItems.some(x => x.recurring === "true") ? "true" : "false", 355 ...(includeUserData && { user_data: p.UserData }) 356 }); 357 console.log("GA4: purchase event detected and pushed."); 358 } 359})(); 360 361//(function () { 362// if (!window.purchaseData) return; 363 364// var p = window.purchaseData; 365 366// window.dataLayer = window.dataLayer || []; 367 368// // Clear ecommerce first 369// dataLayer.push({ ecommerce: null });
370 371// // Build items array including recurring flag on each item 372// var items = p.Items.map(function (item) { 373// return { 374// item_name: item.item_name, 375// item_id: item.item_id, 376// price: item.price, 377// quantity: item.quantity, 378// item_category: item.item_category, 379// item_brand: item.item_brand, 380// item_variant: item.item_variant, 381 382// // recurring status per item 383// recurring: item.recurring ? "true" : "false" 384// }; 385// }); 386 387// // Push purchase event 388// dataLayer.push({ 389// event: "purchase", 390// ecommerce: { 391// value: p.Value, 392// currency: p.Currency, 393// tax: p.Tax, 394// shipping: p.Shipping, 395// transaction_id: p.TransactionId, 396// payment_type: p.PaymentType, 397// ecom_pagetype: "purchase", 398// items: items 399// }, 400 401// // If ANY item is recurring â event-level recurring = true 402// recurring: items.some(x => x.recurring === "true") ? "true" : "false", 403 404// user_data: p.UserData 405// }); 406 407//})();
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.