First, make sure you're comparing the same thing
Before you change any tracking, rule out the differences that aren't tracking problems at all. Shopify's own help pages name time zones and different tracking methods as normal causes of gaps with Google Analytics.
- Time zone: GA4 uses the property's reporting time zone, Shopify uses your store's. If they differ, late-evening orders land on another day. Compare a full week rather than one day.
- Currency: multi-currency stores can report a different currency to GA4 than the one in your Shopify report.
- Test orders: Shopify leaves test orders out of its Sales reports, but a tag on the thank-you page can still send them to GA4.
- Metric: compare Shopify's orders with GA4's purchases first. Only look at revenue once the counts are close.
Why GA4 shows fewer purchases than Shopify
This is the most common direction. A browser tag can only report a purchase if the script loads, is allowed to run, and the buyer's page gets that far.
- Ad blockers and privacy extensions. Shopify's help pages point this out too: customers can block Google Analytics from tracking their sessions and purchases.
- Cookie banners. If a buyer declines, or your banner doesn't pass consent to Shopify, the tag runs in a limited mode or not at all, depending on your setup.
- Payments that leave the checkout. Some buyers pay in PayPal or a bank app and never come back to the thank-you page.
- Express wallets. Buttons like Shop Pay and Apple Pay shorten the route to the order, which is also where merchants report lost attribution and missing browser events.
- Orders without a website visit. Draft orders, POS sales and subscription renewals exist in Shopify but no browser ever saw them, so no tag could fire.
Why GA4 can show more than Shopify
When GA4 reports more purchases or revenue than Shopify, you nearly always have two sources sending the same sale. Typical combinations are the Google & YouTube app next to a Google Tag Manager tag, an old snippet in checkout settings, or a tracking app that nobody removed.
GA4 drops repeat purchases that share a transaction id, per Google's documentation, but only on web streams and only when the id really is the same. If one tag sends the order number and another sends a different order id, GA4 sees two separate sales. The opposite mistake exists too: Google warns against sending an empty transaction id, because all purchases with an empty id get deduplicated together, which can make your numbers far too low.
Why revenue differs when the orders match
If the purchase counts line up but revenue doesn't, look at what's inside the value.
- Shipping and tax: one setup reports the order total, another only the product subtotal.
- Discounts: a tag can report the price before or after the discount code.
- Refunds: Shopify subtracts them from your sales. GA4 keeps the original purchase unless a separate refund event is sent, so GA4 runs higher on stores with many returns.
- Cancelled orders: the sale stays in GA4 after you cancel it in Shopify.
- Profit-based values: if a tool sends profit instead of revenue as the purchase value, GA4 will always show less. Settl has this as an optional setting; if you turn it on, GA4 receives your profit, not your revenue.
Compare one week, order by order
This replaces the guessing. It tells you which orders are missing, and that usually shows the pattern.
- In Shopify, export the orders of one full week, skipping today.
- In GA4, open Explore and make a free-form report with Transaction ID as the dimension and Ecommerce purchases and Purchase revenue as metrics, for the same dates.
- Put both lists in a spreadsheet and look up each order number in the GA4 list.
- Sort the missing orders by payment method, country, device and order source. Most of them from PayPal points to redirects, most from Europe points to consent, and most from POS or subscriptions isn't a tracking problem at all.
- Look for a Transaction ID that exists in two formats, or for rows with a count above 1. Both mean a double setup.
When purchases land under Unassigned or Direct
Sometimes the purchase count is right but the channels are wrong. GA4 connects a purchase to a visit through the client id and session id. When a purchase arrives without them, for example from a server integration that doesn't pass them, GA4 can't put it in the session that came from your ad. It shows up as Unassigned or Direct, and Google Ads can't import it as a conversion for that click.
Google's Measurement Protocol documentation says to include session_id and engagement_time_msec for correct session metrics. A server-side setup is only as good as the identifiers it carries, so check for them before you trust one.
What server-side tracking fixes, and what it doesn't
Sending the purchase from a server solves the technical losses: blocked scripts, closed tabs and redirects no longer matter, because the sale goes out when Shopify reports a paid order. Settl does this through Google's Measurement Protocol. The Settl pixel reads the GA4 client id and session id from the visitor's cookies and keeps them with the visit, and the purchase carries them along with the transaction id, value, currency, products, hashed email and consent signals. Google accepts events backdated by up to 72 hours, so Settl sends the real moment of the order when it can. Every hour Settl also checks the past week's paid orders and sends anything that didn't arrive.
It won't make the two reports identical. Settl sends paid orders only, it doesn't send refunds to GA4, and POS or draft orders have no visit to connect to. A buyer who blocked all cookies has no client id, so the sale still counts but won't sit in the right session. And it doesn't replace consent: you stay responsible for your cookie banner and privacy policy.
One thing to check after you connect it. On Shopify, Settl uses the order name, such as #1001, as the transaction id. If your existing browser tag also sends purchases to the same GA4 property with another id, you'll see each sale twice. Run the check above after a few days, and if you see two formats, switch off the purchase event in one of the two.