Tracking Examples
Ready-to-use recipes built on the xScripts.tracking API.
These scripts can go in the header or footer — handlers only run after Tamio initializes, so they never miss events regardless of placement. Each recipe is self-contained — paste only the ones you need.
Observe all events
Log every native and custom event. Useful while developing.
1 <script> 2 xScripts.tracking.onEvent(function (event) { 3 console.log('Tracking event:', event.type, event.data, event.targets); 4 }); 5 </script>
Send a custom event
Add your own event to the pipeline. It still passes consent and routing.
1 <script> 2 xScripts.tracking.track('merchant_custom_event', { 3 label: 'Example custom event', 4 value: 123, 5 currency: 'SEK', 6 page_path: window.location.pathname 7 }); 8 </script>
Restrict it to specific destinations with the optional third argument:
1 <script> 2 // Send only to Google (GA4 / Google Ads), not Meta. 3 xScripts.tracking.track('google_only_event', { value: 123 }, { platforms: ['google'] }); 4 </script>
Track events on specific pages
Fire a custom event only on matching paths.
1 <script> 2 var pageEvents = [ 3 { match: /^\/(en|sv)\/wholesale(\/|$)/, event: 'view_wholesale_page', data: { area: 'wholesale' } }, 4 { match: /^\/(en|sv)\/campaign\/summer-sale(\/|$)/, event: 'view_summer_campaign', data: { campaign: 'summer-sale' } } 5 ]; 6 7 pageEvents.forEach(function (rule) { 8 if (!rule.match.test(window.location.pathname)) return; 9 10 xScripts.tracking.track(rule.event, Object.assign({}, rule.data, { 11 page_location: window.location.href, 12 page_path: window.location.pathname, 13 page_title: document.title || '' 14 })); 15 }); 16 </script>
Derive a custom event from a Tamio event
Listen to a native event and emit a new one from it. The new event flows to the configured destinations like any other.
1 <script> 2 xScripts.tracking.onEvent(function (event) { 3 if (event.type !== 'purchase') return; 4 5 xScripts.tracking.track('high_value_purchase', { 6 transaction_id: event.data.transaction_id, 7 value: event.data.value, 8 currency: event.data.currency, 9 product_count: (event.data.items || []).length 10 }); 11 }); 12 </script>
Track 30s engagement on product pages (Google Ads conversion)
Goal: fire one distinct event when a visitor stays active on a product page for at least 30 seconds, so it can be used as a Google Ads conversion.
Why a script is needed: Google Ads conversions are matched on the event name, and every page_duration milestone shares that name. GA4's "Create event" can't help here either, because it can only read a single event's own parameters — and "is a product page" lives on a different event (view_item), not on page_duration.
How product pages are detected: view_item is emitted only on product pages, so we use it as the marker (no reliable product URL pattern needed). We remember it, then fire our event when the 30s milestone arrives.
1 <script> 2 (function () { 3 var productView = null; // set when view_item fires → we are on a product page 4 5 xScripts.tracking.onEvent(function (event) { 6 // 1. Product page loaded — remember it and keep the product details. 7 if (event.type === 'view_item') { 8 productView = event.data; 9 return; 10 } 11 12 // 2. 30s of active time reached on that product page → emit the conversion. 13 if (event.type === 'page_duration' && event.data.milestone_seconds === 30 && productView) { 14 var product = (productView.items && productView.items[0]) || {}; 15 16 xScripts.tracking.track('product_engaged_30s', { 17 duration_seconds: event.data.duration_seconds, 18 page_path: window.location.pathname, 19 currency: productView.currency, 20 value: productView.value, // product price → value-based bidding 21 item_id: product.item_id, // explicit → appears in GA4 and Ads 22 item_name: product.item_name, 23 items: productView.items // keep → feeds id/value to the Ads tag 24 }, { platforms: ['google'] }); 25 } 26 }); 27 })(); 28 </script>
Notes:
- Active time pauses when the tab is in the background, so 30s means 30s of real attention.
- The event fires once per product-page visit.
- It reaches both GA4 and Google Ads when both tags are on the page. Define the conversion in one place to avoid double-counting — the simplest is: mark
product_engaged_30sas a Key event in GA4 and import it into Google Ads.
Block low-value milestones
Keep only longer engagement; drop the short page_duration milestones before they reach any destination.
1 <script> 2 xScripts.tracking.onEvent(function (event) { 3 if (event.type === 'page_duration' && event.data.milestone_seconds < 30) { 4 event.preventDefault(); // or: return false; 5 } 6 }); 7 </script>
Keep an event out of one platform
Send page_duration to GA4 but never to Meta. ('google' covers GA4 + Google Ads.)
1 <script> 2 xScripts.tracking.onEvent(function (event) { 3 if (event.type === 'page_duration') { 4 event.preventDefaultFor('facebook'); 5 } 6 }); 7 </script>
Forward an event to your own endpoint
Listen for a Tamio event, build your own payload, and send it to a custom endpoint.
1 <script> 2 var endpoint = 'https://example.com/tracking/purchase'; 3 4 xScripts.tracking.onEvent(function (event) { 5 if (event.type !== 'purchase') return; 6 7 var payload = { 8 order_id: event.data.transaction_id, 9 total: event.data.value, 10 currency: event.data.currency, 11 product_ids: (event.data.items || []).map(function (item) { return item.item_id; }), 12 page_path: window.location.pathname 13 }; 14 15 navigator.sendBeacon(endpoint, JSON.stringify(payload)); 16 }); 17 </script>