Shopify Double-Tracking Prevention
The Problem
Section titled “The Problem”Shopify double-tracking happens when you run both a Shopify GA4 app (like the official Google channel) and a Custom Pixel with GTM that also sends GA4 events.
Here’s what’s happening:
- The Shopify app injects its own
gtag.json every page, firingpage_view,purchase,add_to_cartautomatically - Your Custom Pixel loads GTM, which fires a GA4 Config tag on “All Pages”
- Both fire identical events simultaneously
Result: every GA4 event fires twice, doubling your numbers and breaking downstream analysis.
How to Diagnose Double-Tracking
Section titled “How to Diagnose Double-Tracking”-
Check GA4 DebugView: Open DebugView and load a page. You’ll see pairs of identical events arriving within milliseconds of each other.
-
Check Network tab: Filter requests to
collectrequests togoogle-analytics.com. Count the hits per page load—you should see roughly 2x the expected number. -
Check GA4 Reports: Look at your
page_viewcounts. Inflated numbers (roughly 2x expected traffic) are the telltale sign. -
Query BigQuery: Run this diagnostic on yesterday’s data:
SELECTevent_date,event_name,user_pseudo_id,event_timestamp,COUNT(*) as event_countFROM `project.dataset.events_*`WHERE _TABLE_SUFFIX = FORMAT_DATE('%Y%m%d', CURRENT_DATE() - 1)AND event_name IN ('page_view', 'purchase', 'begin_checkout')GROUP BY 1, 2, 3, 4HAVING event_count > 1ORDER BY event_count DESCLIMIT 100Duplicates with identical
event_timestampvalues confirm double-tracking.
Fix #1: Change GA4 Config Trigger (Simplest)
Section titled “Fix #1: Change GA4 Config Trigger (Simplest)”The quickest fix is to prevent GTM’s GA4 Config from firing on every page:
- Open Google Tag Manager and edit your Google Tag (GA4 Config tag)
- Change the trigger from “All Pages” to a Custom Event trigger—use something like
cookie_consent_updateorconsent_granted - This way GTM’s GA4 only initializes after consent, avoiding conflict with the Shopify app’s automatic tracking
This works because the Shopify app already handles initial page_view events. Your GTM tag now only fires when explicitly triggered, preventing duplication.
Fix #2: The Hybrid Approach (Recommended)
Section titled “Fix #2: The Hybrid Approach (Recommended)”Use Shopify’s app for storefront tracking and Custom Pixels ONLY for checkout:
| Event | Source | Reason |
|---|---|---|
page_view | Shopify App | Already injected, no duplication |
view_item | Shopify App | Product pages, native integration |
add_to_cart | Shopify App | Automatic firing on cart add |
begin_checkout | Custom Pixel | Checkout page only, GTM control |
add_shipping_info | Custom Pixel | GTM-powered consent handling |
add_payment_info | Custom Pixel | GTM-powered consent handling |
purchase | Custom Pixel | Custom transaction handling |
This creates a clean handoff: the Shopify app owns the storefront, your Custom Pixel owns the checkout funnel. No overlap.
Fix #3: Transaction ID Deduplication (Safety Net)
Section titled “Fix #3: Transaction ID Deduplication (Safety Net)”Even with the hybrid approach, add deduplication logic to your purchase handler as a backstop:
// In your Custom Pixel purchase handleranalytics.subscribe('checkout_completed', (event) => { const orderId = event.data.checkout.order?.id || event.data.checkout.token;
// Check if this transaction was already sent // (using pixel's own storage since sessionStorage isn't available) if (window.__trackedOrders && window.__trackedOrders[orderId]) { console.log('Duplicate purchase blocked:', orderId); return; }
window.__trackedOrders = window.__trackedOrders || {}; window.__trackedOrders[orderId] = true;
// Proceed with purchase event push dataLayer.push({ ecommerce: null }); dataLayer.push({ event: 'purchase', ecommerce: { /* ... */ } });});This blocks any purchase event with the same orderId from firing twice in the same session.
GA4’s Built-In Deduplication
Section titled “GA4’s Built-In Deduplication”GA4 automatically deduplicates purchase events with identical transaction_id values within a session. However, this only applies to purchase events. Other events like page_view and begin_checkout have no built-in deduplication, so you must prevent duplicates at the source.
Summary
Section titled “Summary”- Diagnose using DebugView, Network tab, and BigQuery
- Fix with GTM trigger isolation (quickest) or hybrid approach (cleanest)
- Add transaction deduplication for purchase safety
- Test in incognito with one tracking method at a time
Double-tracking isn’t a bug—it’s a config issue. Fix the source, not the data.