Your Shopify dashboard says you did $47,300 last week. GA4 says $41,800. Meta claims it drove $38,000 in purchases on its own. Google Ads adds another $22,000. Your spreadsheet, which pulls from a different export, shows $44,600. None of these numbers agree, and you have no idea which one to trust. This isn't a bug. It's a structural problem — and it has a specific set of causes and fixes.
This is by design, not by accident
Every analytics tool was built with a different purpose, a different data model, and a different definition of "a sale." Shopify was built to process orders. GA4 was built to track user sessions. Meta was built to prove the value of Meta ads. These goals are not aligned, and the numbers they produce reflect those different incentives and architectures.
Understanding why the numbers differ is the first step toward choosing which number to act on — and when. The answer isn't "pick the one you like." It's understanding what each number actually measures.
"Every analytics tool was built with a different purpose. Shopify was built to process orders. Meta was built to prove the value of Meta ads. These goals are not aligned."
The 6 reasons your revenue numbers never agree
Reason 1: Refunds and returns
Shopify deducts refunds from revenue automatically. When a customer returns a $150 order, Shopify subtracts $150 from your revenue total the moment the refund is processed. This is correct accounting.
Most ad platforms don't do this. Meta, Google, and TikTok count the original purchase event — they have no way of knowing the item was returned unless you explicitly send them a refund event via the API (which almost nobody does). So your platform-reported revenue includes sales that were subsequently reversed. For brands with a refund rate above 5%, this gap can be meaningful: a 10% return rate means platform revenue is systematically 10% higher than actual Shopify revenue, all other things equal.
To check your refund rate impact: in Shopify, compare gross revenue (before refunds) vs net revenue (after refunds) in the Finances summary. The difference, as a percentage, tells you how much of your platform-reported revenue is illusory.
Reason 2: Test orders and internal traffic
Every Shopify store has at least a few test orders — placed by the team to check the checkout flow, verify a discount code, or test a new payment method. If those orders aren't properly marked as test orders or refunded immediately, they inflate your Shopify revenue numbers. If they do go through and get attributed to ad clicks (unlikely but possible), they inflate your platform-reported conversions too.
More commonly, internal traffic from your team browsing the store inflates GA4 session data and can create false attribution signals. A team member clicking a Meta ad to check how it looks from the ad to the landing page generates an ad click and a session — but no real purchase intent.
The fix: set up an IP exclusion filter in GA4 (Admin > Data Streams > Configure tag settings > Define internal traffic) to exclude your office and team IP addresses. In Shopify, audit your orders periodically and mark any test orders appropriately. If your team is large or distributed, consider using a separate Shopify development store for all internal testing.
Reason 3: Multi-currency conversion rates
If you sell in multiple currencies, every tool handles currency conversion differently — and those differences add up.
Shopify converts foreign currency orders to your store currency at the exchange rate at the time of the transaction. An order placed on Monday uses Monday's rate. GA4 converts using its own daily exchange rate, which is pulled from a different source and applied differently. Meta uses yet another rate. When exchange rates fluctuate — and they always do — the same underlying order will appear as different revenue amounts in each tool.
In practice, this creates a 2–8% variance on any given week for stores with significant non-home-currency revenue. It's not a reporting error — it's a genuine difference in how the same transaction is valued. The fix is to standardise: always report in your Shopify store currency, use Shopify's converted revenue figures as your single source, and treat platform revenue figures in other currencies as approximate only.
Reason 4: Attribution window differences
This is the big one, and it's the source of most of the dramatic discrepancies you see between platforms.
Every tool has an attribution model — a set of rules for deciding which ad, session, or channel gets credit for a sale. The models are different by default across every tool:
- Meta: 7-day click, 1-day view attribution by default. An order placed up to 7 days after clicking a Meta ad — or 1 day after seeing it — gets credited to Meta. View-through attribution means Meta can claim credit for orders from people who never even clicked.
- GA4: Last-click attribution by default (with data-driven attribution available). The last channel a user clicked before purchasing gets 100% of the credit. If someone clicked a Meta ad on Monday, then came back via Google search on Wednesday to purchase, Google gets the credit in GA4.
- Shopify: First UTM attribution. Shopify records the UTM parameters from the first visit that had UTMs. If a customer first arrived via a Meta ad three weeks ago, Shopify may attribute their purchase to Meta even though their last click was organic.
These models can credit the same order to three different channels simultaneously. The order happened once. The revenue is real once. But Meta, GA4, and Shopify are each counting it under different rules — and all three numbers are internally consistent. None of them is lying. They're just answering different questions.
Meta default: 7-day click + 1-day view. Google Ads default: 30-day click, 1-day view. GA4 default: Last-click, 30-day lookback. Shopify: First UTM seen on the order. None of these windows match each other, which is why the same purchase appears in multiple platforms' conversion reports.
Reason 5: Missing or broken UTM parameters
GA4 attributes sessions using UTM parameters — the tracking tags appended to your ad URLs (utm_source, utm_medium, utm_campaign, etc.). When a customer arrives without UTM parameters — because a link was shared without them, an email client stripped them, or someone bookmarked the page — GA4 counts that session as Direct traffic.
Shopify still records the order as revenue. GA4 still records the session and the conversion. But GA4 attributes it to Direct instead of the channel that actually drove it. From GA4's perspective, Direct revenue was $12,000 last week. From Shopify's perspective, $12,000 of revenue came in that you can't trace to any specific marketing channel.
The gap this creates isn't a discrepancy between tools — both Shopify and GA4 agree on the total revenue. The problem is that your channel-level breakdowns are wrong. You're over-crediting Direct and under-crediting paid and organic channels. This matters enormously when you're trying to make budget allocation decisions based on channel ROAS.
A UTM audit is one of the highest-leverage things you can do for your reporting. Check: every paid ad URL should have utm_source, utm_medium, and utm_campaign set. Email campaigns need UTMs. Social posts with tracked links need UTMs. Any affiliate or influencer links need UTMs. The complete guide to this is in the UTM parameter guide linked at the bottom of this article.
Reason 6: Order timing and timezone differences
This one creates discrepancies that are small but consistent — and particularly confusing at the start and end of reporting periods.
Shopify records order timestamps in UTC by default but displays them in your store's configured timezone. GA4 records events in the timezone you set in your GA4 property settings. Meta and Google Ads report in their own account timezones, which may be different again. An order placed at 11:30pm EST on Sunday appears as:
- Sunday's revenue in Shopify (if your store timezone is EST)
- Monday's conversion in GA4 (if your GA4 property is set to UTC)
- Sunday's conversion in Meta (if your Meta account is in EST)
Over a full week the effect mostly cancels out, but on Sundays and Mondays — and at month boundaries — it creates systematic mismatches. A Monday morning review that shows an unusually strong Sunday might just be UTC orders falling into the previous night. The fix: set your GA4 property timezone to match your Shopify store timezone, and ensure your Meta and Google account reporting timezones match as well.
The discrepancy diagnosis table
| Tool | What it counts as revenue | Common gap vs Shopify net | Fix |
|---|---|---|---|
| Shopify (gross) | All completed orders before refunds | Overstates by refund rate (often 5–15%) | Always use net revenue (after refunds) |
| Shopify (net) | Completed orders minus refunds, your store currency | — This is your truth | Use this as your anchor number |
| GA4 | Purchase events with UTM attribution, last-click | Under-reports by missing UTMs (5–20%); currency variance | Fix UTM coverage; match timezone; use Shopify for totals, GA4 for channel split |
| Meta Ads Manager | Purchases attributed in 7-day click / 1-day view window | Over-reports by 20–80% vs Shopify due to view-through and overlap | Use only for spend and relative performance trends; never for absolute revenue |
| Google Ads | Conversions in 30-day click window, last-click | Over-reports by 10–40% due to window overlap with other channels | Import Shopify conversions via GA4 for more accurate conversion tracking |
| Spreadsheet / manual export | Depends entirely on export source and date | Varies; often stale or using gross revenue accidentally | Automate from a single source; always export net revenue, same timezone |
The hierarchy of truth
When the numbers conflict — and they will always conflict — you need a hierarchy. Here's the one that makes sense:
Shopify is the authority on whether a sale happened. If an order is in Shopify, the sale happened. If it's not in Shopify, it didn't. Platform-reported conversions that don't correspond to Shopify orders are phantom conversions — view-through attributions, duplicate counts, or test events. Always use Shopify net revenue (after refunds) as your total revenue figure.
GA4 is the authority on traffic source — with caveats. GA4's session and traffic source data is the most complete picture of how people are finding your store, assuming your UTM coverage is good. Use GA4 for channel-level traffic splits, funnel analysis, and understanding user behaviour on your site. Don't use GA4 revenue figures as your total — use them only to understand proportional channel contribution.
Ad platforms are the authority on spend. The one number you should always trust from Meta and Google is how much you spent. Their conversion and revenue figures are unreliable for absolute totals due to attribution window overlap and view-through counting. But their spend figures are precise. Use platform spend + Shopify revenue to calculate your own ROAS, rather than using their reported ROAS.
When reporting weekly performance, use this formula: total ROAS = Shopify net revenue attributed to paid channels (via UTM analysis in GA4) ÷ total spend from ad platforms. This approach uses each tool for what it's actually good at and avoids the double-counting and window overlap that makes platform-reported ROAS unreliable.
Five steps to standardise your reporting
You won't eliminate all discrepancies — the tools are genuinely measuring different things. But you can reduce the unexplained gap to under 5%, which is manageable. Here's how:
Step 1: Fix your UTM coverage. Audit every paid URL — Meta ads, Google ads, email campaigns, affiliate links, influencer links. Every external link that can be UTM-tagged should be. Use a consistent naming convention (lowercase, hyphens not spaces, standardised source and medium values). A 15% gap in UTM coverage creates a 15% phantom "Direct" revenue figure that makes every channel attribution wrong.
Step 2: Exclude test orders and internal traffic. Set up IP exclusion in GA4. Create a separate Shopify test account or use draft orders for internal testing. Audit your last three months of Shopify orders and flag any that look like internal tests. Even a handful of large test orders can skew weekly numbers significantly.
Step 3: Set consistent timezones. Your Shopify store, GA4 property, Meta account, and Google Ads account should all report in the same timezone. Pick your store's local timezone and update each platform to match. This is a five-minute fix that eliminates a persistent source of end-of-day and end-of-week discrepancies.
Step 4: Choose one refund treatment and stick to it. Use Shopify net revenue (after refunds) as your revenue figure everywhere. Never mix gross and net in the same analysis. If you're pulling from multiple sources, make sure you're consistently pulling post-refund figures. Document this as a reporting standard so everyone on the team is using the same number.
Step 5: Stop using platform revenue figures for total performance. Meta's reported purchase revenue and Google's reported conversion value are inputs to their internal optimisation algorithms — they're not your financial truth. Use them to understand which ad sets and keywords are performing relatively better or worse, but never use them as your revenue figure. Your revenue figure comes from Shopify. This one discipline eliminates the most dramatic-looking discrepancies.
How DataMaster solves this
The core problem with reconciling these numbers manually is that it requires pulling from four different sources, applying consistent rules across all of them, and doing it every week without making mistakes. That's exactly the kind of repetitive, rule-based work that breaks down under time pressure.
DataMaster solves the discrepancy problem by pulling from Shopify orders directly and working backwards. Instead of trying to reconcile what Meta says it drove with what GA4 says it drove, DataMaster starts from a definitive list of Shopify orders, looks at the UTM parameters on each order, and attributes revenue to channels using a single consistent rule set that you configure once.
Refunds are handled automatically — DataMaster uses net revenue by default. Timezone is set once at the account level and applied consistently everywhere. Multi-currency orders are converted at Shopify's transaction-time rate, which means the numbers match Shopify exactly. Internal traffic exclusions you set in DataMaster are applied to the order attribution, not just to session tracking.
The result is a ROAS figure for each channel that you can actually trust — because it's derived from the same Shopify order data that your finance team uses, not from the ad platforms' self-reported conversion counting. When Meta says your ROAS was 4.2x and DataMaster says it was 2.8x, DataMaster is closer to the truth — and it can show you exactly which orders Meta was double-counting or attributing via view-through to explain the gap.
Revenue discrepancies don't disappear — they get explained. And an explained discrepancy is one you can act on.
See what your actual Shopify-truth ROAS looks like
DataMaster pulls from your Shopify orders directly and applies consistent attribution rules across Meta, Google, and every other channel — so you get one revenue number you can trust, not four that contradict each other.
Start free trial — no credit card required