Integration
Google Tag Manager
Load the tracker with a Custom HTML tag, then turn your existing ecommerce dataLayer events into Seentics purchases.
1. Load the tracker
- In GTM:
Tags → New → Custom HTML. Name itSeentics tracker. - Paste the code below, replacing
YOUR_WEBSITE_IDwith the ID fromSettings → Trackingin Seentics. - Trigger:
Initialization – All Pages(orAll Pages). Save, preview, then publish the container.
<script>
(function () {
if (document.getElementById('seentics-js')) return;
var s = document.createElement('script');
s.id = 'seentics-js';
s.defer = true;
s.src = 'https://seentics.com/trackers/seentics.min.js';
s.setAttribute('data-website-id', 'YOUR_WEBSITE_ID');
document.head.appendChild(s);
})();
</script>This creates the script element with JavaScript rather than pasting the plain tag. The tracker reads its own <script> element for its settings, and an element made this way is the one it finds. Use the plain tag only if you are sure your GTM setup leaves it as a normal script element. The tracker is deferred either way, so anything that calls it must wait for it, as the next step does.
2. Send purchases from the GA4 dataLayer
If your store already pushes the GA4 purchase event, you can reuse it. The push looks like this (your platform or its GTM plugin usually does it for you):
window.dataLayer = window.dataLayer || [];
dataLayer.push({ ecommerce: null }); // clear the previous ecommerce object
dataLayer.push({
event: 'purchase',
ecommerce: {
transaction_id: 'ORD-8821',
value: 49.99,
currency: 'USD',
items: [{ item_name: 'T-shirt', item_id: 'TSHIRT-M', quantity: 2, price: 29.0 }]
}
});- Variables → New →
Data Layer Variable. Name itDLV - ecommerce, Data Layer Variable Nameecommerce, version 2. - Triggers → New →
Custom Event, event namepurchase. Name itEvent - purchase. - Tags → New → Custom HTML, named
Seentics purchase, with the code below and the triggerEvent - purchase.
<script>
(function () {
var e = {{DLV - ecommerce}} || {};
var value = Number(e.value);
if (!isFinite(value)) return;
var items = (e.items || []).map(function (i) {
return { name: i.item_name, sku: i.item_id, qty: i.quantity || 1, price: i.price };
});
var props = {
value: value,
currency: e.currency || 'USD',
order_id: String(e.transaction_id || ''),
product_name: items[0] ? items[0].name : '',
items: items
};
var tries = 0;
(function send() {
if (window.seentics && window.seentics.track) {
window.seentics.track('purchase', props);
} else if (++tries < 100) {
setTimeout(send, 100); // the tracker is deferred: wait for it
}
})();
})();
</script>The mapping is: transaction_id → order_id, value and currency as they are, and each item's item_name, item_id, quantity and price → name, sku, qty and price. Seentics counts one order per order_id, so a reloaded confirmation page does not double the revenue. See Revenue for every property.
Untested in a live container
Consent
Seentics does not read Google Consent Mode signals or the dataLayer. Its own consent handling is separate: by default a visitor in a region that requires consent is asked before recordings start, and you can pass your consent tool's answer in yourself.
- Fire the loader tag only after consent, using your consent tool's trigger, if you want nothing to load before it.
- Or load it always, and add a second Custom HTML tag, triggered when the visitor grants consent, that calls
seentics.consent(true)(andseentics.consent(false)when they withdraw). The tracker remembers the answer. - To skip the tracker's own consent card because you have a banner, add
s.setAttribute('data-consent-banner', 'off')to the loader.
Details are in the tracker reference.