1(function() { 2 'use strict'; 3 4 window.dataLayer = window.dataLayer || []; 5 6 /** 7 * Push GA4 event to dataLayer from JSON string 8 * @param {string} eventJson - JSON string of GA4 event 9 */ 10 function pushGA4Event(eventJson) { 11 try { 12 const eventData = JSON.parse(eventJson); 13 window.dataLayer.push({ ecommerce: null }); 14 window.dataLayer.push(eventData); 15 } catch (error) { 16 console.error('GA4: Failed to parse event JSON', error); 17 } 18 } 19 20 /** 21 * Hook into add to cart AJAX responses to track GA4 events 22 * This intercepts the response from the AddToCart endpoint 23 */ 24 function initAddToCartTracking() { 25 const originalFetch = window.fetch; 26 27 // Override fetch to intercept add to cart responses 28 window.fetch = function(...args) { 29 return originalFetch.apply(this, args).then(response => { 30 // Clone response so we can read it 31 const clonedResponse = response.clone(); 32 33 // Check if this is an add to cart request 34 if (args[0] && args[0].includes('/umbraco/Surface/CartSurface/AddToCart')) { 35 clonedResponse.json().then(data => { 36 if (data && data.ga4Event) { 37 // Push the GA4 event to dataLayer 38 pushGA4Event(data.ga4Event); 39 } 40 }).catch(err => { 41 console.error('GA4: Failed to parse AddToCart response', err); 42 }); 43 } 44 45 return response; 46 }); 47 }; 48 49 // Intercept XMLHttpRequest (for non-fetch AJAX calls) 50 const originalXHROpen = XMLHttpRequest.prototype.open; 51 const originalXHRSend = XMLHttpRequest.prototype.send; 52 53 XMLHttpRequest.prototype.open = function(method, url, ...rest) { 54 this._url = url; 55 return originalXHROpen.apply(this, [method, url, ...rest]); 56 }; 57 58 XMLHttpRequest.prototype.send = function(...args) { 59 this.addEventListener('load', function() { 60 if (this._url && this._url.includes('/umbraco/Surface/CartSurface/AddToCart')) { 61 try { 62 const data = JSON.parse(this.responseText); 63 if (data && data.ga4Event) { 64 pushGA4Event(data.ga4Event); 65 } 66 } catch (e) { 67 console.error('GA4: Failed to parse AddToCart XHR response', e); 68 } 69 } 70 }); 71 return originalXHRSend.apply(this, args); 72 }; 73 74 // Also handle jQuery AJAX if used 75 if (window.jQuery) { 76 $(document).ajaxSuccess(function(event, xhr, settings) { 77 if (settings.url && settings.url.includes('/umbraco/Surface/CartSurface/AddToCart')) { 78 try { 79 const data = JSON.parse(xhr.responseText); 80 if (data && data.ga4Event) { 81 pushGA4Event(data.ga4Event); 82 } 83 } catch (e) { 84 console.error('GA4: Failed to parse AddToCart jQuery response', e); 85 } 86 } 87 }); 88 } 89 } 90 91 // Initialize when DOM is ready 92 if (document.readyState === 'loading') { 93 document.addEventListener('DOMContentLoaded', function() { 94 initAddToCartTracking(); 95 }); 96 } else { 97 initAddToCartTracking(); 98 } 99 100 // Expose functions globally for manual triggering if needed 101 window.GA4Tracking = { 102 pushEvent: pushGA4Event 103 }; 104 105})();
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.