1/* 2 * Eventi ecommerce (GA4-style) verso il dataLayer di Google Tag Manager. 3 * File indipendente, non tocca in alcun modo l'evento onboarding esistente 4 * (quello resta in base_onboarding.twig / ty_confirmed_nonfood.twig). 5 * 6 * Tutti gli eventi sono attivi solo se window.gtmMarketingEnabled === true, 7 * impostato nei template in base a attivita.getMarketing() (colonna has_marketing). 8 * 9 * Ogni funzione e' avvolta in try/catch: un errore qui non deve MAI 10 * interrompere il codice chiamante (checkout, add to cart, ecc.). 11 */ 12(function (window) { 13 "use strict"; 14 15 window.dataLayer = window.dataLayer || []; 16 17 function safeNumber(value) { 18 var n = parseFloat(value); 19 return isNaN(n) ? undefined : n; 20 } 21 22 function cleanItem(item) { 23 item = item || {}; 24 var cleaned = { 25 item_id: item.id !== undefined && item.id !== null ? String(item.id) : undefined, 26 item_name: item.name || undefined, 27 item_category: item.category || undefined, 28 price: safeNumber(item.price), 29 quantity: item.quantity !== undefined ? safeNumber(item.quantity) : undefined 30 }; 31 Object.keys(cleaned).forEach(function (key) { 32 if (cleaned[key] === undefined) delete cleaned[key]; 33 }); 34 return cleaned; 35 } 36 37 function gtmPush(eventName, payload) { 38 if (!window.gtmMarketingEnabled) return; 39 try { 40 var eventData = Object.assign({ event: eventName }, payload || {}); 41 window.dataLayer.push({ ecommerce: null }); 42 window.dataLayer.push(eventData); 43 if (window.gtmDebugMode && window.console && typeof window.console.log === 'function') { 44 window.console.log('[GTM event]', eventName, eventData); 45 } 46 } catch (e) { 47 // Il tracking non deve mai bloccare il resto della pagina. 48 } 49 } 50 51 function ecommercePush(eventName, items, extra) { 52 try { 53 var payload = Object.assign({ 54 ecommerce: Object.assign({ 55 currency: "EUR", 56 items: (items || []).map(cleanItem) 57 }, extra || {}) 58 }); 59 gtmPush(eventName, payload); 60 } catch (e) {} 61 } 62 63 var GtmEvents = { 64 viewItem: function (item) { 65 ecommercePush("view_item", [item], { value: safeNumber(item && item.price) }); 66 }, 67 addToCart: function (item) { 68 ecommercePush("add_to_cart", [item], { value: safeNumber(item && item.price) }); 69 }, 70 removeFromCart: function (item) { 71 ecommercePush("remove_from_cart", [item]); 72 }, 73 viewCart: function (items, value) { 74 ecommercePush("view_cart", items, { value: safeNumber(value) }); 75 }, 76 beginCheckout: function (items, value) { 77 ecommercePush("begin_checkout", items, { value: safeNumber(value) }); 78 }, 79 purchase: function (order) { 80 order = order || {}; 81 ecommercePush("purchase", order.items, { 82 transaction_id: order.transactionId !== undefined ? String(order.transactionId) : undefined, 83 value: safeNumber(order.value) 84 }); 85 }, 86 viewItemList: function (items, listName) { 87 ecommercePush("view_item_list", items, { item_list_name: listName || undefined }); 88 }, 89 selectItem: function (item, listName) { 90 ecommercePush("select_item", [item], { item_list_name: listName || undefined }); 91 }, 92 search: function (searchTerm) { 93 gtmPush("search", { search_term: searchTerm || undefined }); 94 }, 95 addToWishlist: function (item) { 96 ecommercePush("add_to_wishlist", [item]); 97 }, 98 generateLead: function () { 99 gtmPush("generate_lead", {}); 100 } 101 }; 102 103 window.GtmEvents = GtmEvents; 104})(window);
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.