1(function () { 2 'use strict'; 3 4 /** 5 * Fire a GA4 event and log it to the console. 6 * @param {string} eventName - GA4 event name 7 * @param {Object} params - Event parameters 8 */ 9 function trackEvent(eventName, params) { 10 params = params || {}; 11 // console.log('[Tracking] ' + eventName, params); 12 if (typeof gtag === 'function') { 13 gtag('event', eventName, params); 14 } 15 } 16 17 window.trackEvent = trackEvent; 18 19 /** 20 * Build a GA4 ecommerce item object for an edition. 21 * @param {string} editionKey - e.g. 'standard', 'collector' 22 * @param {string} [platform] - e.g. 'direct', 'steam', 'ps', 'xbox' 23 * @returns {Object} GA4 item + currency/value for the event level 24 */ 25 function buildEcommerceItem(editionKey, platform) { 26 var editions = (typeof TebexHeadless !== 'undefined') ? TebexHeadless.editions : []; 27 var edition = null; 28 for (var i = 0; i < editions.length; i++) { 29 if (editions[i].key === editionKey) { edition = editions[i]; break; } 30 } 31 if (!edition) return null; 32 33 var item = { 34 item_id: String(edition.packageId), 35 item_name: edition.name, 36 item_category: platform || 'direct', 37 quantity: 1 38 }; 39 40 // Only include price/value for direct purchases â external platform 41 // prices are set independently and we don't have access to them 42 var result = { item: item }; 43 if (!platform || platform === 'direct') { 44 var priceData = (typeof TebexHeadless !== 'undefined') ? TebexHeadless.prices[editionKey] : null; 45 if (priceData && priceData.price) { 46 var num = parseFloat(priceData.price.replace(/[^0-9.\-]/g, '')); 47 if (!isNaN(num)) item.price = num; 48 } 49 result.currency = (priceData && priceData.currency) ? priceData.currency : 'USD'; 50 result.value = item.price || 0; 51 } 52 53 return result; 54 } 55 56 window.buildEcommerceItem = buildEcommerceItem; 57 58 /** 59 * Build GA4 event params from an ecommerceItem result. 60 * Omits currency/value when they aren't present (external platforms). 61 */ 62 function ecomEventParams(data) { 63 var params = { items: [data.item] }; 64 if ('currency' in data) params.currency = data.currency; 65 if ('value' in data) params.value = data.value; 66 return params; 67 } 68 69 window.ecomEventParams = ecomEventParams; 70 71 /** 72 * Store purchase context in sessionStorage so payment-success.html 73 * can fire the GA4 'purchase' event with item details. 74 */ 75 function storePurchaseContext(editionKey, platform) { 76 var data = buildEcommerceItem(editionKey, platform); 77 if (data) { 78 localStorage.setItem('ga4_purchase_context', JSON.stringify(data)); 79 } 80 } 81 82 window.storePurchaseContext = storePurchaseContext; 83 84 /* ââ view_item: fire once per edition card when it scrolls into view ââ */ 85 /* Call initViewItemObserver() after Tebex prices have loaded so values are available */ 86 var viewItemObserved = {}; 87 function initViewItemObserver() { 88 var observer = new IntersectionObserver(function (entries) { 89 entries.forEach(function (entry) { 90 if (!entry.isIntersecting) return; 91 var card = entry.target; 92 var key = card.getAttribute('data-edition-key'); 93 if (!key || viewItemObserved[key]) return; 94 viewItemObserved[key] = true; 95 96 var data = buildEcommerceItem(key); 97 if (data) { 98 trackEvent('view_item', ecomEventParams(data)); 99 } 100 }); 101 }, { threshold: 0.5 }); 102 103 var cards = document.querySelectorAll('.edition-card[data-edition-key]'); 104 for (var i = 0; i < cards.length; i++) { 105 observer.observe(cards[i]); 106 } 107 } 108 109 window.initViewItemObserver = initViewItemObserver; 110 111 document.addEventListener('click', function (e) { 112 var target = e.target.closest('[data-track]'); 113 if (!target) return; 114 115 var trackType = target.getAttribute('data-track'); 116 var location = target.getAttribute('data-track-location') || ''; 117 118 switch (trackType) { 119 case 'presskit': 120 trackEvent('click_presskit', { link_location: location }); 121 break; 122 123 case 'discord': 124 trackEvent('click_discord', { link_location: location }); 125 break; 126 127 case 'creator_programme': 128 trackEvent('click_creator_programme', { link_location: location }); 129 break; 130 131 case 'platform': 132 var platform = target.getAttribute('data-track-platform') || ''; 133 trackEvent('select_platform', { platform: platform }); 134 break; 135 136 } 137 }); 138})();
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.