Most e-commerce teams know roughly how many orders they're getting. The question they can't answer is why they're losing the ones they don't get. Someone viewed a product, added it to their cart, and vanished. Where? At checkout? On the payment screen? You don't know, because you're only measuring the end state.
GTM and GA4 give you that visibility, but only if you set them up for it — most installs don't.
The setup: GTM sits between your site and everything else
Without GTM, you'd paste a GA4 snippet directly into your HTML, then add another snippet for your ad pixel, then another for your heatmap tool. Each one adds weight to your page and requires a deploy to change.
GTM is a container — one snippet in your <head> that loads and manages all the others. You configure what fires and when through a UI, without touching your codebase. The only code you write is the dataLayer pushes.
Install GTM by adding two snippets to your site. The first goes in <head>:
<script>
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXXX');
</script>
The second is a <noscript> iframe immediately after the opening <body> tag — required for users with JavaScript disabled.
Once GTM is live, create a GA4 tag inside it. In the GTM UI: Tags → New → Google Tag → paste your GA4 Measurement ID (G-XXXXXXXXXX). Trigger: All Pages. Publish. Page views and basic session data start flowing immediately.
The dataLayer: how your site talks to GTM
The dataLayer is a plain JavaScript array — the bridge between your site and GTM. You push structured objects into it; GTM listens and fires tags in response.
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: 'your_event_name',
// any data you want GTM to see
});
Any push with an event key becomes a GTM trigger. The data you push alongside becomes available as variables you can forward into your tags.
Mapping the funnel
GA4 has standard e-commerce event names. Use them exactly — GA4's funnel reports and Looker Studio templates are built around them.
Product viewed:
dataLayer.push({
event: 'view_item',
ecommerce: {
currency: 'USD',
value: 49.99,
items: [{ item_id: 'SKU-001', item_name: 'Leather Wallet', price: 49.99, quantity: 1 }]
}
});
Added to cart:
dataLayer.push({
event: 'add_to_cart',
ecommerce: {
currency: 'USD',
value: 49.99,
items: [{ item_id: 'SKU-001', item_name: 'Leather Wallet', price: 49.99, quantity: 1 }]
}
});
Checkout started:
dataLayer.push({
event: 'begin_checkout',
ecommerce: {
currency: 'USD',
value: 49.99,
items: [{ item_id: 'SKU-001', item_name: 'Leather Wallet', price: 49.99, quantity: 1 }]
}
});
Order placed:
dataLayer.push({
event: 'purchase',
ecommerce: {
transaction_id: 'TXN-8821',
currency: 'USD',
value: 49.99,
tax: 4.50,
shipping: 5.00,
items: [{ item_id: 'SKU-001', item_name: 'Leather Wallet', price: 49.99, quantity: 1 }]
}
});
For each event: create a Custom Event trigger in GTM (matching the event field), then a GA4 Event tag that fires on it and passes the ecommerce object through as event data.
Clear the ecommerce object before each push. Skip this and data from a previous event bleeds into the next one.
dataLayer.push({ ecommerce: null }); // clear first
dataLayer.push({ event: 'add_to_cart', ecommerce: { ... } });
Reading the reports
Once events are flowing, mark purchase as a conversion in GA4 under Admin → Events → toggle "Mark as conversion". Do the same for any lead capture event — form submissions, email signups, whatever counts as a qualified lead in your funnel.
The funnel report is under Explore → Funnel exploration. Add view_item, add_to_cart, begin_checkout, and purchase in order. GA4 shows you the drop-off at each step, filterable by device, traffic source, or any dimension you care about.
For lead generation: push a generate_lead event on form submission, mark it as a conversion, and you can trace which traffic sources are producing leads that eventually turn into purchases.
Things that will catch you out
The purchase event is the easiest one to double-count. Confirmation pages get loaded more than once — refreshes, back-button navigations, payment gateway redirects. If you fire on page load without guarding against it, you'll book the same order twice in GA4. Tie the event to a server-side flag, or at minimum check a session marker before pushing.
Before publishing any GTM changes, run them through Preview mode. It shows every tag that fired, what triggered it, and the full data payload. It's much easier to catch a misconfigured ecommerce object there than to notice it a week later in a funnel report that looks wrong.
One last thing: GA4's Explore section runs on processed data, which lags 24–48 hours behind real time. The real-time view is instant, but that's not where the funnel reports live. If everything looks empty on day one, that's expected.