- On Shopify, server-side tracking sends each purchase from the paid order that Shopify reports by webhook, so it does not depend on the thank-you page loading.
- The visitor id and the ad click ids are saved as cart attributes, so Shopify copies them onto the order and the order can be matched to the click.
- Browser and server events share one event id built from the order id, so Meta, TikTok, Snapchat, Pinterest and Reddit count each purchase once.
- With Respect visitor consent on, a visitor who declines marketing cookies gets no visitor id and their browser events are not sent to ad platforms, but the paid order is still sent with hashed customer data from the order.
- Setup in ROASaurus has four main steps: install the app, switch on the theme app embed, add the checkout pixel and connect your ad platforms.
Server-side tracking on Shopify means that each purchase reaches Meta, TikTok and other ad platforms from your store's order data, sent by a server, and not only from a pixel in the shopper's browser. Shopify reports every paid order to the tracking app by webhook, and the app sends it to each platform's conversions API, matched to the ad click that brought the shopper in.
This guide covers the Shopify parts of that flow: the theme app embed and the app proxy, pixels in checkout, the orders/paid webhook, order matching, deduplication, consent and the setup in ROASaurus. For the general idea, read what server-side tracking is first.
How server-side tracking works on Shopify
The click and the purchase happen at different moments and in different places. The click is only visible in the browser, on the landing page. The paid order is only certain on Shopify's side, when payment is captured. Server-side tracking records the first, waits for the second and joins them.
The Shopify parts: app embed, app proxy, pixels and webhooks
A Shopify store gives a tracking app four places to work. Each one has a different job, and a complete setup uses all four.
| Part | Where it runs | What it does |
|---|---|---|
| Theme app embed | Every storefront page | Loads the tracking script, reads ad click ids and saves the visitor id on the cart |
| App proxy | A path on your own store domain | Receives storefront events as first-party requests |
| Customer events (pixels) | Checkout and thank-you page | Report the checkout steps and the completed checkout from a sandbox |
| Order webhooks | Shopify's servers | Send the order to the app when it is created and when it is paid |
The theme app embed and the app proxy
A theme app embed is a block that an app adds to your theme. You switch it on in the theme editor, so there is no code to paste. The ROASaurus embed loads a script on every page. On the landing page it reads click ids such as fbclid, ttclid and gclid and the UTM parameters, and stores them with a first-party visitor id.
The script sends its events through Shopify's app proxy. An app proxy forwards requests from a path on your own domain, such as yourstore.com/apps/roasaurus, to the app's server. For the browser, this is a request to your own site, which can help against ad blockers that block known tracking domains. Shopify removes the Cookie header from app proxy requests and the Set-Cookie header from the responses, so the visitor id travels inside the event itself, not in a cookie.
Customer events and pixels in checkout
In Shopify's checkout, tracking scripts run as pixels in a sandbox, not in the page itself. You manage them under Settings › Customer events. There are two kinds. App pixels come with an app and run in a strict sandbox. Custom pixels are added by the merchant and run in a less strict sandbox, which can load third-party scripts such as the Meta pixel.
ROASaurus uses both. Its app pixel is switched on when you install the app. It reports the start of checkout, the contact step and the completed checkout to ROASaurus. The optional custom pixel adds the browser pixels of Meta, TikTok, Snapchat, Pinterest and Reddit to checkout, and it sends Google Ads conversions.
Order webhooks
A webhook is a message that Shopify sends to an app when something happens in the store. ROASaurus subscribes to orders/paid and orders/create, among others. The order in the webhook holds the order id, the value, the line items, the customer details, the cart and checkout tokens, the cart attributes, and the IP address and browser the order was placed from. It comes from Shopify's servers, so an ad blocker or a closed tab cannot stop it.
How orders are matched to ad clicks
The webhook tells ROASaurus that an order was paid. To send a useful conversion, ROASaurus also needs to know which visitor placed the order, because the visitor record holds the click ids. It tries these links in order, from the most direct to the least:
| Method | How it works | When it is used |
|---|---|---|
| Cart attribute | The script writes the visitor id and the fbc, fbp, ttp, gclid and ttclid values as cart attributes. Shopify copies them onto the order. | First choice |
| Cart and checkout tokens | The script links the cart token to the visitor, and the checkout pixel links the checkout token. The webhook carries both tokens. | When the cart attribute is missing |
| Checkout event | The checkout pixel reports the completed checkout with the order id and the visitor id. | When no token matches |
| Email address | The hashed email of a visitor who entered it earlier, for example at the contact step of checkout. | When there is no checkout event |
| IP address and browser | A visitor seen with the same IP address and browser shortly before the order. | Only when exactly one visitor fits |
Cart attributes are the reason matching is direct on Shopify. They are key-value pairs stored on the cart, and Shopify copies them onto the order. A value written on the product page is still there when the webhook arrives, even if the shopper closed the thank-you page early.
One exception: accelerated checkout buttons such as Buy it now skip the cart. ROASaurus advises turning them off, so that Add to cart is always tracked. Orders placed through them can still match through the checkout token.
One order, end to end
Here is what happens for a single order from a Meta ad, with the custom pixel installed:
page_view ?fbclid=IwAR2x…A shopper lands from a Meta ad. The click id is stored with visitor 3f2a.cart _tl=3f2a _tl_fbc=fb.1.…The visitor id and the Meta click value are saved as cart attributes.checkout_started ic-c1a9…The checkout token is linked to the same visitor.checkout_completed order-6123456789012The checkout pixel reports the order, and the Meta pixel sends Purchase with this event id.orders/paid #1042 id 6123456789012 $86.00Shopify sends the paid order by webhook.Meta CAPI Purchase order-6123456789012After a short hold, the server event goes out with the click ids, IP address and user agent.When the purchase is sent: orders/paid or orders/create
Which webhook triggers the purchase depends on how your customers pay. You choose it as the checkout type in Store settings.
| Checkout type | Webhook | When the purchase is sent |
|---|---|---|
| Shopify checkout | orders/paid | When the order is paid. Orders that are never paid are not sent. |
| External / COD checkout | orders/create | When the order is created. For cash on delivery, and for checkouts such as Checkify and CheckoutChamp that create Shopify orders. |
ROASaurus holds each purchase for a short time after the webhook arrives. In that time, the completed-checkout event from the browser usually arrives too. Its page URL, IP address and user agent are then added to the server event, next to the click ids from the visitor record. Orders that Shopify marks as test orders are recorded but not sent to the ad platforms.
How deduplication works with the browser pixels
When the browser pixels run next to the server events, the platform receives each purchase twice and must keep only one. It does that with the event id. ROASaurus gives both copies of a purchase the same id, built from the Shopify order id: order-6123456789012 for the order with id 6123456789012. This is the long number in the order's admin URL, not the order name such as #1042. The checkout pixel uses it for the browser Purchase, and the server uses it for the conversions API event. Meta, for example, keeps one copy when the event name and the event id match and both arrive within 48 hours.
| Platform | Browser pixel from ROASaurus | Deduplicated with the server event |
|---|---|---|
| Meta, TikTok, Snapchat, Pinterest, Reddit | Storefront and checkout | Yes |
| X, Microsoft Advertising, Taboola | None, server events only | Nothing to merge |
| Google Ads | Checkout only, through the custom pixel | Sent once, from the checkout |
The event id only works between events that carry it. If another app sends the same pixel, its events have their own ids, and the platform counts the order again. On Shopify, the usual causes are the Facebook & Instagram channel connected to the same pixel, the TikTok app, and pixel code pasted into theme.liquid. Our guide to duplicate purchase events shows how to find them, and Prevent double counting lists the fixes.
Consent through Shopify's Customer Privacy API
Shopify's Customer Privacy API stores each visitor's cookie choice. Your cookie banner fills it in, whether you use Shopify's own banner or a consent app connected to the API. Scripts and pixels can then ask it whether marketing is allowed for this visitor.
With Respect visitor consent on, which is the default in Store settings, the ROASaurus storefront script and checkout pixels ask the API before they track.
- A visitor id, click ids and browsing events are stored
- The browser pixels load and send events
- The paid order is sent server-side and matched to the ad click
- No visitor id is set, so their visits and ad clicks are not linked to them
- Browser events are kept without a visitor id, IP address or browser details, and are not sent to ad platforms
- The paid order is still sent server-side with hashed customer data from the order, and the order's IP address and user agent
- The event that reaches the ad platform carries no click id
Emails, phone numbers, names and addresses are hashed with SHA-256 before they are sent to an ad platform. Three more details matter:
- Your banner decides. ROASaurus follows what the API reports. If the API is not available on the page, ROASaurus treats the visitor as consenting, so check that your banner is connected to it.
- The landing page stays on the order. Shopify stores the landing page address with each order, and it can contain campaign tags and click ids. ROASaurus uses it in its own attribution reports, also for visitors who declined, and does not send it to the ad platforms.
- Sending the order is a legal decision. Whether the paid order of a visitor who declined may be sent at all is a legal question for your store.
Our guide to Consent Mode v2 and GDPR explains the rules at a high level, and Consent and privacy has the details.
How to set up server-side tracking on Shopify in ROASaurus
Do the setup steps in this order:
- Install the app
Go to Add a store, choose Shopify, enter your
.myshopify.comdomain and click Install app. Approve the app in Shopify. ROASaurus registers the order webhooks and switches on its app pixel. - Switch on the theme app embed
On the Tracking & platforms page, click Open theme editor, switch on the ROASaurus app embed and save.
- Add the checkout pixel
In Shopify admin, go to Settings › Customer events and add a custom pixel named ROASaurus. Set its permission to Not required, because the ROASaurus script checks the visitor's marketing choice itself. Paste the snippet from Tracking & platforms. You need this pixel for browser pixels in checkout and for Google Ads.
- Connect your ad platforms
On Tracking & platforms, click Add pixel for each platform, or Connect with Facebook for Meta. Keep the option to also load the browser pixel on if you want deduplicated browser events.
- Check the store settings
In Store settings, choose your checkout type and keep Respect visitor consent on if you sell where consent is required.
- Remove other senders
In the Facebook & Instagram channel, remove this pixel from the data sharing settings. Lowering the data sharing level is not enough, because every level, including Standard, sends the Meta pixel from the browser. If the TikTok app sends the same pixel, stop it there too, and remove pixel code from your theme.
The custom pixel snippet looks like this. Copy it from Tracking & platforms, where your store key is already filled in. The Shopify setup guide has the same steps.
self.tl = this; document.head.appendChild(document.createElement('script')).src = 'https://app.roasaurus.com/c.js?k=YOUR_STORE_KEY';How to check that it works
Test with one real order before you rely on the numbers:
- Open your store with
?roasaurus=connectedat the end of the URL. A message confirms that the script is live. - For Meta, paste the code from Events Manager › Test events into the Test event code field of the pixel.
- Place a real, low-priced order and refund it afterward. Shopify test orders are not sent.
- In the Event log, the server delivery for the order shows as sent for each platform, with the platform's response.
- In the platform's test view, check that the browser and the server Purchase share the event id
order-plus the Shopify order id. - Remove the test event code afterward.
What server-side tracking on Shopify does not fix
- Declined consent. Orders from visitors who declined marketing cookies are sent, but without a click id, so the ad platforms match them less well.
- Safari's cookie limits. A shopper who returns after more than 7 days can look like a new visitor. A first-party tracking subdomain keeps collection on your domain, but Safari may still cap those cookies at 7 days.
- Attribution differences. Each ad platform still credits sales with its own windows and models. To compare channels with one set of rules, use your own attribution.
- Other apps on the same pixel. Event ids only merge events that share them.
What it does fix is the purchase that happened but never reached the ad platform because the browser event was lost. For what ROASaurus sends to each platform, see server-side tracking and the Shopify integration.
Sources
- Shopify: Customer Privacy API
- Shopify: Authenticate app proxies
- Shopify Help Center: Manage your custom pixels
- Shopify Help Center: Facebook data sharing
- Meta: Handling Duplicate Pixel and Conversions API Events
In ROASaurus
- Help: set up ROASaurus on Shopify
- Shopify integration
- Server-side tracking in ROASaurus
- Help: consent and privacy