GA4 & Tracking

Shopify Server-Side Tracking: Customer Events, Webhooks and sGTM

Customer Events for browser signals, order webhooks for purchases, and one shared order ID for deduplication: how I build server-side tracking on Shopify.

Shopify Server-Side Tracking: Customer Events, Webhooks and sGTM
Quick answer

Shopify server-side tracking combines a Customer Events custom pixel for browser events with order webhooks that send purchases to a server-side GTM container, which forwards them to Meta CAPI, GA4, Google Ads and TikTok. Use the Shopify order ID as the shared event ID, and turn off app integrations that send the same events.

Key takeaways
  • Checkout extensibility moved tracking into Customer Events, where pixels run in a sandbox.
  • Order webhooks record purchases even when the thank-you page never loads in the browser.
  • Webhooks carry no browser cookies, so store click IDs and client IDs against the cart or checkout.
  • Use the same order ID format as the event ID on browser and server events.
  • One purchase source per platform: disable overlapping app integrations.

Most Shopify stores I audit have the same pattern: three or four apps all trying to track the same purchase, a GA4 property that misses orders, and a Meta account that reports more sales than the store received. Shopify has made tracking more locked down with checkout extensibility, which is good for security but confusing for anyone who used to paste scripts on the thank-you page. This guide explains how I build Shopify server-side tracking today, using Customer Events for browser events and order webhooks for purchases, so every platform gets one clean, deduplicated stream.

What is Shopify server-side tracking?

Shopify server-side tracking means sending your store's events, especially purchases, to ad and analytics platforms from a server instead of relying only on the visitor's browser. The server can be server-side Google Tag Manager (sGTM) hosted on Stape or Google Cloud, which forwards events to the Meta Conversions API (CAPI), Google Ads, GA4 and the TikTok Events API.

On Shopify, a solid setup has two layers:

  1. Browser events (page views, product views, add to cart, checkout steps) captured with Shopify Customer Events and sent to your web and server GTM containers.
  2. Purchases from Shopify's backend, sent by order webhooks to your server container, so a purchase is recorded even when the browser never loads the thank-you page or a blocker stops the script.

If you are new to the concept, start with what server-side tracking is, then come back here.

What does checkout extensibility change for tracking?

Checkout extensibility means you can no longer run your own scripts directly on Shopify's checkout and thank-you pages. Shopify retired checkout.liquid and the old "Additional scripts" box on the order status page, and moved tracking into Settings > Customer events, where pixels run in a sandbox.

What that means in practice:

  • Custom pixels run in an isolated sandbox. They can subscribe to Shopify's standard events, but they cannot freely read or change the page around them.
  • GTM can run inside a custom pixel, but its dataLayer lives inside the sandbox, and the normal GTM Preview mode does not connect to checkout the way it does on a theme page. Test with the browser console and your server container's Preview mode instead.
  • App pixels from the Facebook & Instagram, Google & YouTube and TikTok apps also run through Customer Events, and some of them already send server events. This is the main source of duplicates.

How does the setup work end to end?

The setup works by sending browser events through a custom pixel to sGTM, and sending each paid order from a Shopify webhook to the same server container, with the order ID as the shared event ID. Here is the architecture I use most:

Layer Source Events Destinations
Browser Customer Events custom pixel + web GTM page_viewed, product_viewed, product_added_to_cart, checkout_started, checkout_completed GA4, Meta Pixel, TikTok Pixel, Google Ads (via sGTM)
Server sGTM on a first-party subdomain (Stape) Browser events forwarded with server enrichment GA4, Meta CAPI, TikTok Events API, Google Ads
Backend Shopify order webhook (orders/paid or orders/create) Purchase Meta CAPI, TikTok Events API, GA4 Measurement Protocol

Step 1: Map a first-party tracking subdomain

Create your server container in GTM, host it on Stape (or Google Cloud Run), and map a subdomain such as track.yourstore.com to it with a DNS record. A first-party subdomain helps cookies and requests be treated as belonging to your store. Stape's Shopify app can also help send the data layer and webhook data to the container, which saves a lot of custom code.

Step 2: Add a custom pixel for browser events

In Settings > Customer events, add a custom pixel that subscribes to Shopify's standard events and pushes them into GTM. A simplified purchase subscription looks like this:

analytics.subscribe('checkout_completed', (event) => {
  const checkout = event.data.checkout;
  window.dataLayer = window.dataLayer || [];
  window.dataLayer.push({
    event: 'purchase',
    event_id: String(checkout.order.id),
    ecommerce: {
      transaction_id: String(checkout.order.id),
      value: checkout.totalPrice.amount,
      currency: checkout.currencyCode
    }
  });
});

Map the other standard events to GA4 ecommerce names (view_item, add_to_cart, begin_checkout) with item arrays. My GA4 ecommerce checklist lists the parameters each event needs, and the GA4 dataLayer generator gives you correctly shaped pushes to start from.

Step 3: Capture browser identifiers for the webhook

Order webhooks come from Shopify's servers, so they do not carry the visitor's browser cookies. To attribute a webhook purchase, you need identifiers such as _fbp, _fbc (Meta), _ttp and ttclid (TikTok), the GA4 client_id and session ID, and the Google click ID (gclid).

There are two common ways to connect them to the order:

  • Store them against the cart. A small storefront script or an app writes the identifiers into cart attributes, which appear on the order as note attributes in the webhook payload.
  • Store them in a server-side lookup. The browser sends the identifiers to sGTM with the cart or checkout token, and the server container looks them up by that token when the webhook arrives. Stape offers a store and lookup feature built for this.

Step 4: Send purchases from an order webhook

Create a webhook for the order topic you want and point it at your server container's URL (or let the Stape app manage it). Then build server tags that turn the webhook into purchase events for each platform.

Which topic to use matters:

  • orders/paid fires when the order is marked paid. It suits stores where payment is captured at checkout.
  • orders/create fires when the order is created. For cash on delivery stores, which are very common in Bangladesh, orders/paid may only fire days later when the courier collects payment, so orders/create is usually the better trigger for ad optimization.

Also filter out orders you do not want to report, such as point-of-sale, draft or test orders, and verify the webhook's HMAC signature header so nobody can post fake orders to your endpoint.

How do you deduplicate browser and server purchases?

You deduplicate by sending the same event name and the same event ID from both the browser and the webhook, using the Shopify order ID as that ID. Meta and TikTok both use the event ID to merge a Pixel event with its server event, so the purchase is counted once. Make sure both sides use the same format: if the pixel sends 1234567890 and the webhook sends #1001 (the order name) or a Shopify GID, they will not match.

Platform by platform:

  • Meta: eventID in the Pixel and event_id in CAPI must match. My guide to Meta CAPI event deduplication covers the testing process.
  • TikTok: use the same event_id in the TikTok Pixel and the Events API. I cover the full setup in TikTok Pixel and Events API setup.
  • GA4: I usually pick one purchase source, either the browser event through sGTM or the webhook through Measurement Protocol, rather than both. Always send transaction_id, and when using the webhook, include the stored client_id and session_id so the purchase attaches to the right session.
  • Google Ads: the conversion needs a click ID or hashed customer data to be attributed. I normally send the purchase from the browser through sGTM with enhanced conversions, and use the webhook data as a backup check rather than a second conversion.

Turn off duplicate app tracking

This is the step people skip. If the Facebook & Instagram app is set to share data at a level that includes server events, and your sGTM setup also sends CAPI purchases to the same Pixel, the two will use different event IDs and double-count. The same applies to the Google & YouTube app sending GA4 and Google Ads conversions alongside your GTM tags. Choose one source per platform and disable the others in the app settings or under Customer events.

How do you test Shopify server-side tracking?

You test it by placing real orders and following each event from Shopify through sGTM to every platform. My checklist:

  • Server container Preview mode shows the webhook request arriving and each server tag returning success.
  • Meta Test Events shows the purchase from browser and server with the same event ID.
  • TikTok Events Manager shows the purchase without duplicate warnings.
  • GA4 DebugView and later the monetisation reports show one purchase with the correct transaction ID and value.
  • Google Ads conversion diagnostics show the purchase with enhanced conversions data.
  • Over the following weeks, platform purchase counts are compared with Shopify orders for the same dates.

On Modalclo, a Shopify fashion brand, I replaced a browser-only Pixel with deduplicated Pixel and Conversions API events using GTM and Stape, plus GA4 enhanced ecommerce mapped to Shopify product and checkout data. For a broader look at app-based options, see Meta Conversion API on Shopify and WooCommerce.

Final thoughts

The best Shopify server-side tracking setups are not the ones with the most apps; they are the ones where each platform receives one clean purchase with a shared order ID. Use Customer Events for browser signals, webhooks for reliable purchases, and switch off overlapping integrations. If you want this built properly, see my Shopify conversion tracking page and advanced conversion tracking service, or book a free tracking audit.

Related
Chamok Mahonto
Written by Chamok Mahonto

I'm a conversion tracking & google ads specialist from Rangpur, Bangladesh. I set up GA4, GTM, server-side tracking and Meta Conversion API, and manage Google Ads for businesses worldwide. More about me

FAQ

Frequently asked questions

Can I still add tracking scripts to the Shopify thank-you page?

No. With checkout extensibility, Shopify retired the Additional scripts box and checkout.liquid. Checkout and thank-you page tracking now runs through Customer Events, either with app pixels or a custom pixel that subscribes to events like checkout_completed.

Should I use orders/paid or orders/create for purchase tracking?

Use orders/paid when payment is captured at checkout, because it only fires for paid orders. For cash on delivery stores, orders/paid may fire days later, so orders/create usually gives ad platforms a timelier purchase signal. Filter out test, draft and point-of-sale orders either way.

Do I need Stape for Shopify server-side tracking?

Not strictly. You can host server-side GTM on Google Cloud and build the webhook handling yourself. Stape makes it easier with managed hosting, a custom domain, a Shopify app and lookup features that connect webhook orders to browser identifiers.

Will Shopify's Facebook & Instagram app conflict with my server-side setup?

It can. If the app sends server events and your sGTM setup also sends Conversions API purchases to the same Pixel, the event IDs will differ and Meta will count orders twice. Choose one server source for each Pixel.

Does GTM Preview mode work on Shopify checkout?

Not in the usual way. Custom pixels run in a sandbox, so GTM Preview does not connect to checkout pages as it does on theme pages. Test with the browser console, your server container's Preview mode and each platform's test events tools.

Case studies

See it in a real project

Modalclo: Meta Pixel & CAPI project by Chamok Mahonto
Meta Pixel & CAPI

Modalclo

Deduplicated Pixel + Conversions API and GA4 enhanced ecommerce for a Shopify loungewear brand, recovering purchases lost to iOS restrictions and ad blockers.

  • Meta Pixel
  • Conversions API
  • GA4 Enhanced eCommerce
Read case study
Keep reading

Related articles

Ready to fix your tracking and scale your ads?

Get a free audit of your tracking and ad account. Usually replies within 1–2 hours.