Skip to content
EARNST.
Tracking & Compliance

E-Commerce Tracking on Shopify: Setup, Attribution & Data Quality

Typically, Shopify stores lose 20 to 40% of all conversion data. Data loss causes, 18+ events, engagement scoring, checkout attribution, Meta CAPI deduplication, and the 17-point tracking audit in one guide.

EARNST · · 45 min read

Key Takeaways

  • Smart Bidding typically optimizes on approximately 60% of data: every missing data point can cost you ROAS directly
  • Engagement Score makes retargeting audiences differentiable: hot leads vs. bouncers instead of blanket approach
  • Example scenario: 170 counted purchases at 100 real = ROAS 4.53 instead of 2.67, budget scaling on false basis
  • 17 checkpoints can help identify tracking errors that distort ROAS, CPA, and audience performance

Typically, Shopify stores lose between 20% and 40% of all conversion data. The causes are well known: ad blockers typically block 15 to 30% of users completely, Safari limits cookies to 7 days, Consent Mode v2 is missing or incorrectly implemented. And on the most important page, the thank-you page, most stores have less data than on the product page.

All percentage and EUR figures in this article are indicative values based on typical e-commerce scenarios. Actual impact depends on industry, audience, existing setup, and other factors.

This guide covers everything you need for complete e-commerce tracking on Shopify: from event architecture through checkout attribution and Meta CAPI deduplication to the 17-point tracking audit. Four topics, one coherent guide.

Table of Contents

  1. The Data Loss Problem: Where Conversions Typically Disappear
  2. Event Architecture: Implementing 18+ Events Correctly
  3. Engagement Scoring: Measuring User Quality
  4. Visitor Identity: Recognizing Every Customer
  5. Checkout and Thank-You Page: The Most Important Data Point
  6. Enhanced Conversions and User Data
  7. Meta CAPI and Event Deduplication
  8. Server-Side Tracking
  9. The EARNST Tracking Audit: 17 Checkpoints in 30 Minutes
  10. GA4 Automation

1. The Data Loss Problem: Where Conversions Typically Disappear

Data loss occurs at four systematic points. Each has measurable financial consequences.

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

Typically, 15 to 30% of all users use ad blockers. For Google and Meta, these users are completely invisible.

Data Loss from Cookie Restrictions: Safari and Firefox

Safari limits JavaScript cookies to 7 days. 35 to 45% of all mobile users in the DACH region use Safari.

Missing Engagement Data: Algorithms Flying Blind

97 to 98% of your visitors do not buy. Without engagement data, Smart Bidding has no idea which of these 98% are valuable prospects.

Consent Tracking Gap: Modeling Impossible

Without correct Consent Mode v2, GA4 cannot apply Behavioral Modeling. The visits disappear completely. Details on consent implementation in the GDPR Tracking Guide.

Cumulative Impact

40 to 60% of your real conversion data is missing from Google Analytics and advertising algorithms. The subset is biased toward Chrome desktop users without ad blockers.


2. Event Architecture: Implementing 18+ Events Correctly

Most Shopify stores track page view, add to cart, purchase. That is 3 data points. A complete setup tracks 18+ events across the entire funnel.

The Architecture: 5 Theme Files + Web Pixel

The setup consists of 5 theme files, a Web Pixel for the checkout, and GTM API tooling. No external dependency, no vendor lock-in.

ComponentTypePurpose
cookie-banner.liquidSnippetCustom CMP with Shopify Customer Privacy API, bilingual, GDPR-compliant
gtm-tracking-head.liquidSnippetConsent defaults, cookie check, GTM loader, server-side DataLayer
gtm-tracking.jsAssetClient-side event tracking, engagement, identity, click-ID persistence
consent-debug.liquidSnippetConsent debugging tool with violation detection and CSV/JSON export
Web PixelShopify Custom PixelPurchase tracking in checkout sandbox with session stitching
GTM API ScriptsPython ToolingReproducible provisioning of both GTM containers

Server-Side DataLayer

Liquid renders page-type-dependent data as structured JSON. On a product page, product data is ready; on a collection, the product list; in search, the search terms and results; in the cart, the cart items.

The Complete Event Funnel

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
ConversionpurchaseWeb Pixel (recommended) or Order Status Script (deprecated August 2026)

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

Five Technical Optimizations with Measurable Impact

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 get through. Result: can capture up to 15 to 20% more select_item events.

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 (Shopify.on("cart:item-added")) is theme-agnostic and robust.

Navigation delay at checkout. The checkout button triggers navigation. Without a delay, the begin_checkout event is lost. preventDefault() followed by a 150ms timeout is invisible to the user but crucial 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 remove and cache the data. Otherwise, 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 every 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]
  }
});

3. Engagement Scoring: Measuring User Quality

97 to 98% of your visitors do not buy. But not all are equally worthless. An engagement score (0 to 100) quantifies the difference between highly interested prospects and bouncers.

The Signals

Five engagement signals feed into the score. Each is measured with native browser APIs, no performance impact.

Scroll Depth is measured via IntersectionObserver: 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 dwell time, not tab timer. The timer pauses on visibilitychange (tab not active) and runs only when the user is actually on the page. Milestones at 10, 30, 60, 180, and 300 seconds.

Product Image Interaction counts unique images viewed via Shopify's Swiper events. Back-and-forth swiping does not distort 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. If the cart stays open for 30 seconds without checkout navigation, an abandonment signal fires.

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) and pushed to the DataLayer, stored as a custom dimension in GA4.


4. Visitor Identity: Recognizing Every Customer

Safari deletes the GA4 cookie after 7 days. The user is "new" on every visit. This distorts attribution, customer journey reports, and retargeting audiences.

Triple Identity Stitching

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 months lifetime). It is ITP-resistant. Safari users remain identifiable for months, not just 7 days.

Click-ID Persistence and Meta Cookie Generation

Click IDs (gclid, gbraid, wbraid, fbclid) are extracted from URL parameters on first page load and stored as first-party cookies (90 days) plus sessionStorage.

Cross-Session Product Interest

Products viewed in the current session are stored in sessionStorage. Products ever viewed are stored in localStorage with a counter.


5. Checkout and Thank-You Page: The Most Important Data Point

The purchase event is the most valuable data point in your entire setup. Most setups have less data on the thank-you page than on the product page. Our setup has the most there.

The Shopify Checkout Problem

Shopify hosts the checkout on a separate domain (checkout.shopify.com). This means: your theme code does not work there, cookies from your main domain are not readily accessible, and consent status must be read again.

Web Pixel: The Future-Proof Solution

Shopify Custom Pixels are JavaScript code running in a sandbox in the checkout. They have access to analytics.subscribe events and can load a separate GTM container, independent of theme code.

Note on Order Status Script: Shopify has marked "Additional Scripts" on the Order Status Page as deprecated (deadline: August 2026). Web Pixels are the future-proof replacement.

MethodAccess ToConsentGTMStatus
Web Pixel (recommended)analytics.subscribe eventsShopify Customer Privacy APISeparate GTM instanceActively developed
Order Status ScriptOrder object, LiquidCustom consent checkSeparate GTM instanceDeprecated (August 2026)

Purchase Event: Single Firing

Shopify's first_time_accessed ensures the event fires exactly once: even on page reload. Double revenue in GA4 is one of the most expensive tracking errors.

Click-ID Persistence Across the Domain Change

When the user switches from yourshop.com to checkout.shopify.com, cookies are lost. Click IDs and session data stored on the main domain are not accessible on the checkout domain.


6. Enhanced Conversions and User Data

The thank-you 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.

Enhanced Conversions Data Guide

FieldShopify LiquidPreparationHash
Emailorder.emaildowncaseSHA256
Phoneorder.billing_address.phoneDigits only + country codeSHA256
First Nameorder.billing_address.first_namedowncase, trimSHA256
Last Nameorder.billing_address.last_namedowncase, trimSHA256
Cityorder.billing_address.citydowncase, trimSHA256
Stateorder.billing_address.province_codedowncaseSHA256
ZIPorder.billing_address.zipRemove spacesPlain text
Countryorder.billing_address.country_codedowncasePlain text

7. Meta CAPI and Event Deduplication

Meta has recommended using the Conversions API (CAPI) alongside the browser pixel since 2023. The reasoning is sound: ad blockers typically block the pixel for 15 to 30% of users, the server-side CAPI delivers data independently of browser restrictions. But "maximizes data coverage" also means: every event is potentially sent twice.

Without event deduplication, Meta can count 30 to 80% more purchases than actually occurred. Your ROAS looks fantastic, your budget planning is based on phantom numbers.

Meta's Deduplication Mechanism

Meta deduplicates events based on two fields: event_name and event_id. If Meta receives two events with identical event_name and identical event_id within 48 hours, the second event is recognized as a duplicate and discarded.

Requirements for the event_id

The event_id must:

  • Be unique per event instance. Each purchase needs its own ID. Two different purchases must not share the same ID.
  • Be identical between pixel and CAPI. Browser and server must send exactly the same ID for the same purchase.
  • Be stable. No regeneration on page reload.

What Works as an event_id

SourceExampleSuitable?
Shopify Order ID#1042 -> purchase_1042Yes, stable and unique
Transaction ID5312847Yes, identical between browser and server
Random UUID (generated per client)a3f7c2d-...Only if the exact same UUID goes to both Pixel AND Server
Random UUID (generated per request)b8e1f4a-... (Pixel) vs c9d2e5b-... (Server)No, different IDs = no deduplication
Timestamp1711382400No, pixel and server have slightly different timestamps

The safest option: the Shopify Order ID or Transaction ID as the basis. This exists in both contexts and is by definition unique per purchase.

Implementation in Shopify

Step 1: event_id in the DataLayer. The purchase event contains the transaction_id. This is used as the basis for the event_id:

dataLayer.push({
  event: 'purchase',
  event_id: 'purchase_' + transactionId,
  ecommerce: {
    transaction_id: transactionId,
    value: orderValue,
    currency: 'EUR',
    items: [...]
  }
});

Step 2: event_id in the pixel. Note the spelling: eventID (camelCase) in the pixel, event_id (snake_case) in the CAPI.

fbq('track', 'Purchase', {
  value: orderValue,
  currency: 'EUR',
  content_ids: contentIds,
  content_type: 'product'
}, {
  eventID: eventId  // camelCase in pixel
});

Step 3: event_id in the CAPI. The GTM Server Container sends the CAPI request with the same event_id:

{
  "data": [{
    "event_name": "Purchase",
    "event_id": "purchase_1042",
    "event_time": 1711382400,
    "user_data": { "em": ["hashed_email"] },
    "custom_data": { "value": 149.90, "currency": "EUR" }
  }]
}

Step 4: Web Pixel for checkout events. The Web Pixel uses the Order ID from the event payload:

analytics.subscribe('checkout_completed', (event) => {
  const orderId = event.data.checkout.order.id;
  const eventId = 'purchase_' + orderId;
  // Pixel event with event_id
  // CAPI receives the same event_id via the server
});

All Events That Need Deduplication

Eventevent_id SourceExample
PurchaseTransaction ID / Order IDpurchase_1042
AddToCartProduct ID + Timestamp Bucketatc_7829384_202603251430
InitiateCheckoutCheckout Tokenic_abc123def456
ViewContentProduct ID + Session IDvc_7829384_sess_a3f7c2d
AddPaymentInfoCheckout Tokenapi_abc123def456
LeadForm ID + Submission Timestamplead_contact_202603251430

Google vs. Meta: Different Approaches

AspectGoogleMeta
Deduplication keytransaction_idevent_id
Automatic?Yes, for purchasesNo, must be explicitly sent
Affected eventsPurchase onlyAll events with event_id
Time windowNot documented (hours to days)48 hours

Debugging and Validation

After implementation, verify that deduplication works:

  1. Events Manager > Pixel > Test Events
  2. Select event (e.g., Purchase)
  3. Check: "Event received from" shows "Browser" and "Server"
  4. Check: "Event ID" shows the same value for both sources
  5. Status: "Deduplicated" or "Not deduplicated"

Monitoring: Measuring Deduplication Rate

Conversion comparison: Compare the number of purchase events in Meta with actual orders in Shopify. The ratio should be between 0.95 and 1.05. A ratio above 1.2 indicates deduplication problems.


8. Server-Side Tracking

Typically, 15 to 30% of your users are blocked by ad blockers. Server-side tracking via a custom subdomain makes your tracking ad-blocker-resistant.

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.

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.

Cookie Lifetime 13 Months: Server-side set cookies with HttpOnly flag bypass Safari ITP completely. Safari users remain identifiable for months, attribution works again.


9. The EARNST Tracking Audit: 17 Checkpoints in 30 Minutes

In our experience, in approximately 8 out of 10 audits, errors are revealed that can distort reported revenue by 20 to 200%. A tracking system that fires events is not automatically a tracking system that delivers correct data.

Audit Toolkit (All Free)

  • Chrome DevTools (Console, Network, Application tabs)
  • Google Tag Assistant (Chrome Extension)
  • GA4 DebugView (GA4, Admin, DebugView)
  • GTM Preview Mode
  • An incognito window (for consent tests)

Block 1: Consent and Compliance (Checkpoints 1 to 4)

Checkpoint 1: Do consent defaults load before GTM? Inspect DevTools, Elements, <head>, first <script> tag. The consent default block must precede the GTM snippet. In our experience, at approximately 60% of stores, consent defaults load after GTM or not at all. Impact: can lead to up to 30% less data recovery for users who decline. Rating: Defaults before GTM = good | Defaults after GTM = warning | No defaults = critical

Checkpoint 2: Does Consent Mode v2 work correctly? Incognito, open shop, click "Decline," Network tab, filter on "collect?", pings with gcs=G100 (= denied) should be visible. Without Behavioral Modeling, you can lose up to approximately 70% of recoverable data. Rating: Correct denied pings = good | No pings = warning | Granted pings despite decline = critical

Checkpoint 3: What is your consent rate? Benchmark: 50 to 65% = standard CMP, 70 to 80% = good, 80 to 90% = optimized, above 90% = suspicious. Typically, every percentage point of consent can lead to approximately 1% more tracking coverage. Rating: above 75% = good | 55 to 75% = warning | below 55% = critical

Checkpoint 4: Is consent revocation possible? GDPR requires consent to be as easily revocable as it is given. In our experience, approximately 40% of stores have no option for this. Rating: Easily accessible = good | Only by deleting cookies = warning | Not possible = critical

Detailed coverage of the consent topic in the GDPR Tracking Guide.

Block 2: Data Quality (Checkpoints 5 to 8)

Checkpoint 5: Are prices correct? Shopify delivers prices in cents (4990 instead of 49.90). In our experience, in approximately 25% of stores, revenue in GA4 is off by a factor of 100. Rating: Prices in EUR (49.90) = good | Prices in cents (4990) = critical

Checkpoint 6: Ecommerce clear before every push? Before every e-commerce event, dataLayer.push({ ecommerce: null }) must be present. The most common Enhanced E-Commerce bug: items "bleed" into subsequent events. Rating: Ecommerce null before every push = good | Items from previous events visible = critical

Checkpoint 7: Does purchase fire exactly once? Test order, thank-you page, reload page 3 times, check GA4 DebugView. In our experience, in approximately 15% of stores, purchase fires on every reload. Impact: double or triple revenue in GA4. Rating: Exactly once = good | Multiple on reload = critical

Checkpoint 8: Is the GA4 item schema correct? Required fields: item_id, item_name, price, quantity. Recommended: item_brand, item_category. Common errors: price as string instead of number, missing item_category. Rating: All required fields + item_brand + item_category = good | Required fields only = warning | Fields missing = critical

Block 3: Tracking Coverage (Checkpoints 9 to 12)

Checkpoint 9: Which events are tracked? Minimum 6 events (page_view, view_item, add_to_cart, begin_checkout, purchase), good with 10+, excellent with 12+ including engagement. Rating: 12+ events = good | 6 to 11 = warning | below 6 = critical

Checkpoint 10: Does server-side tagging work? DevTools, Network, filter on "gtm.js." From which domain is it loaded? In our experience, approximately 85% of stores load GTM from googletagmanager.com. Without SST, you can lose up to 15 to 30% of users. Rating: Custom domain = good | Google domain = warning | No GTM = critical

Checkpoint 11: How long do your cookies last? DevTools, Application, Cookies, _ga cookie, check expiry date. Safari users have 7-day cookies. Impact: attribution collapses after 8 days. Rating: Server-side cookie 13 months = good | JS cookie 7 days Safari = warning | No cookie = critical

Checkpoint 12: Does the GTM fallback work? Enable ad blocker, load store, check if tracking gets through. In our experience, in approximately 95% of stores: zero tracking with active ad blocker. Rating: Fallback active = good | Partial = warning | Completely blocked = critical

Block 4: Attribution and Conversion Quality (Checkpoints 13 to 17)

Checkpoint 13: Enhanced Conversions active? Google Ads, Conversions, purchase conversion, Diagnostics. Typically, 5 to 15% fewer attributed conversions without Enhanced Conversions. Rating: Active, coverage above 80% = good | Active, coverage below 50% = warning | Not set up = critical

Checkpoint 14: Meta Conversions API active? Meta Events Manager, Data Sources, Pixel, Overview. Are "Server" events visible? Event Match Quality should be above 6. Rating: Server + Browser, EMQ above 6 = good | Browser only = warning | Not active = critical

Checkpoint 15: Do GA4 and Google Ads match? Compare purchase counts. Below 10% difference = good. Above 25% = serious problem. Rating: below 10% difference = good | 10 to 25% = warning | above 25% = critical

Checkpoint 16: Click-ID persistence Click a Google ad, check if gclid is stored as a cookie. Lifetime at least 90 days. Rating: Cookie 90d + sessionStorage + url_passthrough = good | Cookie with short lifetime = warning | No persistence = critical

Checkpoint 17: Event deduplication Meta Events Manager, Test Events. Is the purchase event marked as "Deduplicated"? Rating: event_id present, "Deduplicated" = good | event_id present, not verified = warning | No event_id = critical

The Audit Scorecard

ScoreMeaning
14 to 17 green checkpointsYour setup is solid. Optimization potential in details.
9 to 13 green checkpointsAction needed. The gaps cost you measurable money.
Below 9 green checkpointsYour tracking is fundamentally broken. Fix tracking first.

10. GA4 Automation

Via the GA4 Admin API, the following are automatically set up: key events, 15 custom dimensions, custom metrics, and 12 retargeting audiences.

The 15 Custom Dimensions

DimensionScopePurpose
engagement_scoreUSERRetargeting segmentation
visitor_typeUSERNew vs. returning
consent_statusUSERConsent rate tracking
product_interest_levelUSERCross-session interest
returning_product_viewEVENTRepeat visitor signal
scroll_depthEVENTContent engagement
active_time_secondsEVENTTrue dwell time
product_images_viewedEVENTProduct interest depth
new_customerEVENTNew customer flag for NCA Bidding
cart_valueEVENTCart segmentation
consent_regionEVENTRegion-based consent analysis
click_id_sourceEVENTAttribution source
device_engagementEVENTDevice-specific engagement
checkout_stepEVENTCheckout funnel analysis
event_idEVENTDeduplication monitoring

Cost: EUR 0 Instead of Approx. EUR 100 to 600 Monthly

The entire setup requires no external apps or services. No tracking app (approximately EUR 100 to 300/month), no external CMP (approximately EUR 25 to 200/month), no analytics app (approximately EUR 50 to 150/month). Over a 3-year period, potential savings of approximately EUR 3,600 to 21,600.

The 10 Most Common Errors: What We See in Audits

  1. Prices in cents. Shopify delivers 4990, GA4 shows EUR 49,900 instead of EUR 49.90.
  2. No ecommerce clear. Items from the previous event bleed into subsequent events.
  3. Consent Mode after GTM. The first hits without consent signal. Can lead to up to 30% less Behavioral Modeling.
  4. click instead of mousedown. select_item events are lost.
  5. No GTM fallback. Ad blocker means zero tracking for 15 to 30% of users.
  6. Purchase fires multiple times. Double revenue in GA4.
  7. No first-party identity. Safari users are "new" after 7 days.
  8. Engagement equals bounce rate. No data for retargeting segmentation.
  9. Same data for all page types. Collection data on the product page.
  10. PII in plain text. Email unhashed in the browser.

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

Comparison and Conclusion

CriterionTypical SetupEARNST SetupBusiness Impact
Events tracked3 to 518+3 to 5x more data points
Consent Mode v2Incorrect or missingCorrect sequence + custom bannerCan recover approx. 70% of conversions
Server-side trackingNoFirst-party domain, SST containerCan improve attribution by up to 15 to 30%
First-party identityNo13-month cookie, triple IDSafari attribution works
Engagement scoreNo0 to 100, weighted compositeCan improve retargeting ROAS by up to 40%
Enhanced ConversionsNo or faultySHA256 server-side in LiquidMaximum data quality
Event deduplicationNoevent_id for all eventsNo double conversions
GA4 AutomationManual15 custom dimensions, 12 audiencesImmediately usable segmentation
Tracking auditNone17 checkpoints, self-verifiableDetect errors in 30 minutes
Monthly costsApprox. EUR 100 to 600EUR 0 (excl. SST hosting)Potential savings approx. EUR 3,600 to 21,600

How much does your setup lose? We will find out. Tracking Audit in 48 hours, with concrete numbers, concrete recommendations, and a clear roadmap.

Sources

Data Loss Layers in Shopify Store

Meta Conversion Tracking: Before / After

Reported Conversions

100

ROAS (reported)

2.7

x

Event Match Quality

8

/ 10

Attribution Accuracy

92

%

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

How can we help you?

Choose your perspective — we'll tailor the content for you.