Skip to content
EARNST.
Tracking & Compliance

Enterprise-Grade E-Commerce Tracking on Shopify — No App, No Agency, No Compromise

Your Shopify store loses 20–40% of all conversion data. That costs you ad performance, attribution, and revenue. Here is how to get that data back.

EARNST · · 20 min read

Key Takeaways

  • 20–40% of your conversion data is missing — ad blockers, Safari ITP, and missing consent signals distort your ad optimisation
  • Complete tracking system in 3 files + custom cookie banner. No app, no monthly costs, no vendor lock-in
  • 18+ events instead of the usual 3–5 give Google Ads 3–5x more data points for Smart Bidding
  • Engagement score 0–100 separates hot leads from bouncers — usable as a bidding signal and retargeting criterion
  • Server-side tracking with first-party domain keeps Safari users identifiable for 13 months instead of 7 days

Your Shopify store is losing money. Not because your products are bad or your prices are wrong — but because your tracking infrastructure loses between 20% and 40% of all conversion data. This means Google and Meta optimise your campaigns on incomplete data. You are paying for advertising that is served based on estimates, not facts.

With an ad spend of 10,000 euros per month and 30% data loss, your campaigns optimise on 7,000 instead of 10,000 euros worth of conversion data. This distorts Smart Bidding, retargeting audiences, and ROAS calculations. The distortion is not random: you disproportionately lose mobile users, Safari users, and privacy-conscious audiences — often the segments with the highest purchasing power.

The causes are well known: ad blockers block 15–30% of users completely. Safari limits cookies to 7 days. Consent Mode v2 is missing or incorrectly implemented. Server-side tagging does not exist.

What most stores do: install an app, click three buttons, and assume they have tracking. The reality: duplicate purchase events, prices in cents instead of euros, first hits without a consent signal.

What we built: a complete tracking system in 3 files, one admin script, and a custom cookie banner. No app dependency, no monthly costs, no external dependencies. Board-level data quality.

What You Are Losing — and What It Costs

This section is the most important in the entire article. It is not about technology. It is about money.

Data Loss from Ad Blockers: 15–30% of Users Invisible

Every blocked user is invisible to Google and Meta. No conversion tracking, no retargeting, no attribution. With a conversion rate of 2% and an average order value of 80 euros, this means: out of 10,000 monthly visitors, 1,500 to 3,000 are completely missing from your data. That is potentially 30 to 60 unattributed conversions — 2,400 to 4,800 euros per month that do not appear in any ROAS calculation.

Data Loss from Cookie Restrictions: Safari and Firefox

Safari limits JavaScript cookies to 7 days. 35–45% of all mobile users in the DACH region use Safari. A user who sees your ad on Monday and buys the following Tuesday is a "new visitor" for GA4. The conversion is not attributed to the campaign. Your ROAS looks worse than it is — and Smart Bidding optimises downward.

Missing Engagement Data: Algorithms Flying Blind

Google Ads Smart Bidding optimises for conversions. But 97–98% of your visitors do not buy. Without engagement data (scroll depth, time on page, product image interaction), the algorithm does not know which of those 98% are valuable prospects and which are bouncers. It treats them all the same — and wastes budget.

Consent Tracking Gap: Modelling Impossible

Without correct Consent Mode v2, you lose an additional 30% of remaining data. GA4 cannot apply behavioural modelling without a consent signal — the visits disappear completely instead of being modelled.

Cumulative Impact

Total: 40–60% of your real conversion data is missing from Google Analytics and the advertising algorithms. You are optimising on a subset of your customers — and the subset is not even representative. It is skewed toward Chrome desktop users without ad blockers.

What this means for you: every bidding decision, every audience, every ROAS report is based on a distorted data foundation. Not because Google or Meta work poorly — but because your setup does not provide them with the data they need.

All 9 chapters as a 10-page PDF

Architecture, Consent Mode, server-side tracking, engagement scoring, identity, purchase automation — concise executive summary.

Download PDF

No form, no gate. Questions? [email protected]

The Architecture — 3 Files, Zero Cost

Instead of 50–300 euros per month for a tracking app and 50–300 euros per month for a cookie banner service, you pay: zero euros in monthly software costs. The setup consists of 3 files, one admin script, and a custom cookie banner. No external dependency, no vendor lock-in, full control.

ComponentTypePurpose
gtm-tracking-head.liquidSnippetConsent defaults, cookie check, GTM loader, server-side DataLayer
gtm-tracking.jsAsset (675 lines)Client-side event tracking, engagement, identity
Cookie BannerSnippetCustom CMP, bilingual, GDPR-compliant, zero dependencies
Order Status ScriptAdmin scriptPurchase event on the thank-you page
GA4 AutomationAdmin APIKey events, custom dimensions, retargeting audiences

The architecture follows a clear principle: Liquid renders server-side data into a structured object, JavaScript consumes that data client-side, and GTM remains a pure event router — not a code execution layer.

This is a deliberate decision against the common approach of packaging tracking logic into GTM Custom HTML tags. Tag-in-tag constructs create race conditions, cannot be cached, do not support defer, and are difficult to debug. A cached JS asset on the Shopify CDN solves all four problems simultaneously.

Why this is better than an app: no third-party script slowing down your site. No vendor changing their pricing model. No black-box code you cannot audit. Over a 3-year period, you save 1,800 to 10,800 euros in app and CMP fees — while running a setup that is technically superior.

Consent Mode v2 + Custom Cookie Banner — Saving 70 out of 100 Euros

Without correct Consent Mode v2, you discard the entire session with every "Reject" click. With a correct setup, GA4 recovers approximately 70% of this data through behavioural modelling. With an opt-out rate of 40% (DACH average), that is the difference between 60% and 88% data coverage.

The Correct Sequence

Most implementations load Consent Mode defaults after the GTM script. This is the most common mistake, and it has measurable consequences: the first hits of a session reach Google without a consent signal. GA4 cannot start behavioural modelling for these hits — the data is irretrievably lost.

The correct chain: set consent defaults, check stored cookie, load GTM, show the banner if no cookie exists. No flexibility in the sequence.

// 1. Consent Defaults FIRST — before GTM, before anything else
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('consent', 'default', {
  ad_storage: 'denied',
  ad_user_data: 'denied',
  ad_personalization: 'denied',
  analytics_storage: 'denied',
  wait_for_update: 500
});
// 2. Check cookie → 3. Load GTM → 4. Show banner if needed

Custom Cookie Banner Instead of CMP Subscription

Our cookie banner is not a compromise. It is bilingual (DE/EN), accessible, GDPR-compliant, reopenable, and has zero dependencies — no external script, no iframe, no tracking the tracker.

Consent optimisation within legal boundaries: visual hierarchy (Accept as primary button, Reject as text link), positive framing, no X-close button, an 800ms delay before display. The page remains usable in the background — no blocking overlay that drives users toward quick rejection. Everything legal, everything transparent, measurably higher opt-in rates.

Cost comparison: a CMP service costs 50 to 300 euros per month. Our banner costs 0 euros per month. Over 3 years, that is 1,800 to 10,800 euros saved — for a banner that is better integrated technically than any external tool.

Server-Side Tracking — Recovering the 15–30%

15–30% of your users are blocked by ad blockers. These users do not exist for Google Ads — no retargeting, no attribution, no conversion tracking. Server-side tracking via a custom subdomain makes your tracking ad-blocker-resistant. Additionally, server-side cookie setting extends the lifetime from 7 days (Safari) to 13 months.

A custom subdomain (e.g. tracking.yourdomain.com) points to a server-side GTM container running on Google Cloud Run. From the browser's perspective, this is a first-party request — no ad blocker intervenes, no ITP limits apply. If the SST container is unreachable, an automatic fallback to the Google CDN activates. Zero downtime: no event is lost.

What Server-Side Tracking Additionally Enables

Meta Conversions API: server-to-server communication, completely ad-blocker-resistant. Google Ads Enhanced Conversions: hashed user data directly from the server. Effective Client-ID: backup of the GA4 client ID in a custom cookie that is ITP-resistant.

Server-Side DataLayer

Liquid renders page-type-dependent data as structured JSON. On a product page, product data is available; on a collection page, the product list; in search, the search terms and results; in the cart, the cart items. JavaScript only consumes what is present — no redundant API calls, no DOM queries.

Price conversion is the number one error from tracking audits. Shopify delivers prices in cents — a product at 49.90 euros arrives as 4990. Without conversion, GA4 shows revenue of 4,990,000 euros. The division by 100 happens server-side in Liquid, before the data reaches the browser.

Enhanced Conversions use SHA256 hashing — server-side, in Liquid. No PII reaches the browser in plain text. Email, phone number, name, and address are hashed before they leave the server. User data is only passed for logged-in customers — privacy by default.

Enhanced E-Commerce — Measuring Every Step in the Funnel

Most Shopify stores track Page View, Add to Cart, Purchase. That is 3 data points. That is like a sales conversation where you only know the beginning and the end. Our setup tracks 18+ events across the entire funnel — 3 to 5 times more signals for Smart Bidding and retargeting.

Funnel StageEventTrigger
Discoveryview_item_listCollection or search page load
Interestselect_itemMousedown on product card
Considerationview_itemProduct page load
Intentadd_to_cartNative Shopify PubSub event
Actionbegin_checkoutCheckout button click
ConversionpurchaseOrder status script

Additionally: remove_from_cart, view_cart, search, engagement events, and cart abandonment signals for complete funnel analysis.

Technical Quality as Proof

Every event contains decisions born from dozens of tracking audits. Five of them demonstrate the difference between an app installation and a professional setup.

mousedown instead of click on product cards. When clicking a product card, the browser navigates immediately. The click event fires, but the GTM request often does not reach Google in time. mousedown fires approximately 100 milliseconds before click — enough time for the event to transmit reliably. Without this optimisation, select_item events are missing from your funnel.

PubSub instead of DOM hacking. Many implementations try to intercept the fetch request to /cart/add.js or observe DOM changes via MutationObserver. Both are fragile and break on theme updates. Shopify's native PubSub system is the robust alternative — it works regardless of the theme.

Navigation delay on checkout. The checkout button triggers a navigation. Without delay, the begin_checkout event is lost. We use preventDefault() followed by a 150ms timeout. This is invisible to the user but critical for data quality.

Pre-fetch on cart remove. After removing a product, /cart.js returns the updated cart — without the removed item. We fetch the cart before the removal and cache the data. Otherwise, the item data is missing from the remove_from_cart event.

Ecommerce clear before every push. The most common Enhanced E-Commerce bug: items from the previous event bleed into the next one. An {ecommerce: null} push before each e-commerce event prevents this reliably.

// Ecommerce clear: prevents item bleeding between events
dataLayer.push({ ecommerce: null });
dataLayer.push({
  event: 'view_item',
  ecommerce: {
    currency: 'EUR',
    value: 49.90, // Already converted to euros
    items: [itemData]
  }
});

Engagement Scoring — Knowing Who Wants to Buy

97–98% of your visitors do not buy. But not all of them are equally worthless. Someone who views 5 of 8 product images, opens 3 specification tabs, and spends 4 minutes on the page is an entirely different prospect than someone who bounces after 3 seconds. Our engagement score (0–100) quantifies this difference — and makes it usable for Google Ads and retargeting.

The Signals

Scroll depth is measured via IntersectionObserver — not via scroll event listeners that block the main thread. 4 invisible sentinel elements at 25, 50, 75, and 90 percent page height. Zero performance impact, automatic repositioning on window resize.

Active time measures real time on page, not tab timers. The timer pauses on visibilitychange (tab not active) and only runs when the user is actually on the page. Milestones at 10, 30, 60, 180, and 300 seconds. 300 seconds of active time on a product page is a strong purchase signal.

Product image interaction counts unique images viewed via Shopify's Swiper events. No back-and-forth swiping distorts the data.

Accordion and tab openings capture whether the user actively opens specifications, descriptions, or other detail sections.

Cart abandonment signal: a MutationObserver watches the cart drawer. When the cart remains open for 30 seconds without checkout navigation, an abandonment signal fires — directly from the browser, without waiting for GA4 data processing.

The Scoring Matrix

SignalPointsLimit
Scroll 90%20
Active time 300s25
Product images (per image)5max 20
Accordions (per section)5max 15
Variant changed10
Add to cart10
Total possible100

Practical Application

The score is debounced (5 seconds) before pushing to the DataLayer. What you do with it:

GA4 Audience "High Engagement No Purchase" (score > 60, no purchase within 14 days) — targeted retargeting with higher bids. GA4 Audience "Casual Browsers" (score < 20) — lower bids or exclusion. The score functions as a bidding signal for Google Ads Smart Bidding.

What this means for you: instead of "visited the page", you segment by "was highly interested" — and bid accordingly. One client was able to increase their retargeting ROAS by 40% with engagement-based audiences — because they stopped spending budget on bouncers.

Visitor Identity — Recognising Every Customer

When a user clicks your Google ad on Monday, visits your site on their phone on Tuesday, and buys on desktop on Wednesday — your current setup knows nothing about it. Safari deletes the GA4 cookie after 7 days. The user is "new" on every visit. This distorts your attribution, your customer journey reports, and your retargeting audiences.

Triple Identity Linking

The setup does not rely on a single identification method. Three independent identities are linked:

IdentifierSourceFunction
Custom UUIDCustom visitor cookieIndependent of third parties, first-party, 13 months
GA Client-ID BackupCustom cookieITP-resistant copy of the GA4 client ID
Shopify Visitor IDshopify_yCross-reference point to the shop system

The custom visitor identifier is set as a server-side cookie (HttpOnly, 13-month lifetime). It is ITP-resistant — Safari users remain identifiable for months, not just 7 days.

Click-ID Persistence

Click IDs (gclid, gbraid, wbraid, fbclid) are persisted in a custom cookie (90-day lifetime). This ensures attribution works even when the user switches tabs or the session is interrupted. No loss of campaign attribution due to cookie expiry.

Cross-Session Product Interest

Products viewed in the current session are stored in sessionStorage. Products ever viewed go into localStorage with a counter. When a user returns and views the same product again, the system sets a returning_product_view flag.

What this means for you: "viewed 8 products, bought none" is a comparison shopper — they need a different ad approach than "visited 1 product three times", who is close to purchasing. On login, the customer ID is linked: deterministic cross-device identity without guessing.

Purchase Tracking + GA4 Automation — The Most Important Hit

The purchase event is the most valuable data point in your entire setup. It determines how Google Ads and Meta optimise, which audiences are built, and how your ROAS is calculated. Most setups have less data on the thank-you page than on the product page. Our setup has the most.

Single Execution

Shopify's first_time_accessed ensures the event fires exactly once — even on page reload. Duplicate revenue in GA4 is one of the most costly tracking errors: it corrupts all reports, bidding signals, and ROI calculations.

Maximum User Data

The order status page is the only point where all customer data is available: email, phone number, name, shipping address, billing address. Everything is hashed with SHA256 server-side in Liquid and passed as Enhanced Conversions parameters. Maximum data quality for Google Ads and Meta — without PII in the browser. The new_customer flag for Google Ads New Customer Acquisition bidding is set based on customer.orders_count.

GA4 Property Automation

Via the GA4 Admin API, the following are automatically configured: key events, 15 custom dimensions (engagement score, visitor type, product interest level, cart value tier, and more), custom metrics, and 12 retargeting audiences. Including: High-Value Cart Abandoners, Engaged Non-Buyers, Product Comparers, Returning Product Viewers.

Custom DOM events (dl:view_item, dl:add_to_cart, etc.) function as a GTM-independent bridge for on-site personalisation. Even if an ad blocker completely blocks GTM, these events work.

The 10 Most Common Errors — What We See in Audits

We regularly audit tracking setups of Shopify stores with 500,000 to 10 million euros in revenue. These 10 errors appear in over 80% of all audits — and every single one costs money directly because it undermines the data quality of your advertising algorithms.

  1. Prices in cents. Shopify delivers 4990, GA4 shows 49,900 euros instead of 49.90 euros. Your revenue report is off by a factor of 100.
  2. No ecommerce clear. Items from the previous event bleed into subsequent events. GA4 attribution is wrong.
  3. Consent Mode after GTM. First hits without a consent signal. Approximately 30% less behavioural modelling.
  4. click instead of mousedown. select_item events are lost. Funnel analysis has gaps.
  5. No GTM fallback. Ad blockers mean zero tracking for 15–30% of users.
  6. Purchase fires multiple times. Duplicate revenue in GA4. ROAS calculation is fantasy.
  7. No first-party identity. Safari users are "new" after 7 days. Attribution collapses.
  8. Engagement equals bounce rate. No data for retargeting segmentation.
  9. Same data for all page types. Collection data on the product page. Reports unusable.
  10. PII in plain text. Email unhashed in the browser. GDPR violation and security risk.

Our setup avoids all 10 — by design, not by accident.

Comparison and Conclusion

CriterionTypical SetupEARNST SetupBusiness Impact
Events tracked3–518+3–5x more data points for Smart Bidding
Consent Mode v2Incorrect or missingCorrect sequence + custom banner~70% conversion recovery on opt-out
Cookie bannerExternal, 50–300 euros/monthCustom, 0 euros/month1,800–10,800 euros saved over 3 years
Server-side trackingNoFirst-party domain, SST container15–30% more attributed conversions
First-party identityNo13-month cookie, triple IDSafari attribution works again
Engagement scoreNo0–100, weighted compositeRetargeting ROAS up to 40% better
Cross-session interestNolocalStorage + returning_product_viewComparison shoppers identifiable
Enhanced ConversionsNo or brokenSHA256 server-side in LiquidMaximum data quality for Google + Meta
GA4 AutomationManual15 custom dimensions, 12 audiencesImmediately usable segmentation
App dependencyYesNoneNo vendor lock-in
Monthly cost100–600 euros (app + CMP)0 euros (excl. SST hosting)3,600–21,600 euros saved over 3 years

675 lines of JavaScript, 3 Liquid files, 1 admin script, 1 custom cookie banner. No dependencies, no apps, no monthly costs. This is not "good tracking for a Shopify store". This is tracking at the level most enterprise setups aspire to — but rarely achieve.

How much is your setup losing? We will find out. Free tracking audit in 48 hours — with concrete numbers, concrete recommendations, and a clear roadmap.

Sources

Our service

Tracking & Data Architecture

20–40% of your conversion data is missing. Server-side tracking, Consent Mode v2, 18+ events, and engagement scoring bring it back.

Learn more