All segments

Conversions API: What Syncs, What Doesn't, What Breaks

Conversions API for Shopify: what reaches Meta, what never does, and the three failures (double counts, phantom orders, thin match keys) with a fix for each.

  • Published
  • Reading time 14 min read
  • Author Nafiul Hasan
Conversions API: What Syncs, What Doesn't, What Breaks. Diagram: two records, drifting. REACH Conversions API: What Syncs, WhatDoesn't, What Breaks SYSTEM ASYSTEM B pointerflow.com

Short answer

The Conversions API sends purchase and checkout events from your server to Meta, so ad reporting survives blocked browsers. On Shopify it syncs orders and checkout events but not refunds, renewals or consent by default. Three things break: duplicate senders, orders no ad caused, and match keys lost after checkout.

Most write-ups of the Conversions API explain what it is and stop where the trouble starts. This one covers what nobody documents for the Shopify and Meta pair: the three ways it fails quietly while every dashboard stays green, and the check that catches each.

This article is written for operators at roughly $3M to $30M in revenue, on Shopify Plus or another paid subscription platform, who already spend on Meta and have been told “we’ve set up server-side tracking”. It isn’t written for a brand below the $3M floor, or one spending so little on Meta that a default install is the right answer.

What does the Conversions API change for a Shopify store?

The Conversions API lets your server, not just the shopper’s browser, tell Meta that something happened. The Meta Pixel is JavaScript running in a page. If the page is blocked, the script never loads, the consent banner suppresses it, or the shopper closes the tab before it fires, Meta hears nothing. A server-to-server call doesn’t depend on any of that.

Two names cause confusion, so it helps to settle them. “Conversion API”, “FB Conversions API” and “CAPI” all refer to the same Meta product. It is not Google’s setup, which has its own equivalents. Meta also calls the destination a dataset (older material says Pixel), and the two terms can point at the same object.

On Shopify there are three practical ways to run it. The first is the Facebook and Instagram sales channel app, which sends events server-side alongside the browser Pixel. The second is a server-side tag manager container that you host. The third is a partner or custom integration that listens to Shopify webhooks and posts to Meta. Each works. They fail in different ways, and mixing them is the single most common source of trouble.

What the API changes is the reliability of the signal. What it doesn’t change is what Meta does with it. Attribution windows, modelled conversions and delivery optimisation are still Meta’s. A cleaner feed makes those systems better informed. It doesn’t make Meta’s reporting an audit of your business, and no published benchmark says how much uplift to expect, so any vendor quoting one is guessing.

What a server event needs to carry

A server event has to include an event name, a timestamp, an action source (for a store, the website), and customer information parameters. For a purchase it also needs a value and a currency. Meta expects the customer details hashed, using SHA-256 after trimming and lowercasing. It expects a few identifiers unhashed: the browser cookie values _fbp and _fbc, the client IP address and the client user agent.

Meta rejects events that arrive too late, and the limit is Meta’s to change. Read the current figure in Meta’s developer documentation before designing any retry queue.

What syncs from Shopify to Meta, and what doesn’t?

Shopify’s channel app covers the standard shopping funnel. The table lists what a typical deployment sends and where the gaps sit; the takeaway is that the app follows the shopper’s path well and knows nothing about what happens to an order afterwards.

DataSent by browser PixelSent by serverGap to watch
Page view, view contentYesYes, if enabled in the appBlocked browsers lose the browser copy
Add to cartYesYesCart changes made by apps or scripts may not fire
Initiate checkoutYesYesDepends on checkout configuration
PurchaseYesYesOnly the placed order, never later changes
Refund or cancellationNoNoMeta keeps counting the purchase
Subscription renewalNo (no browser)Only if your sender reads itOften lands as Purchase with no ad behind it
Point-of-sale and draft ordersNoDepends on the senderRarely an ad outcome
Consent stateBrowser banner onlyOnly if the sender checks itServer events can outlive a “no”
Customer lifetime valueNoNoNot a standard event

Read the “Sent by server” column as a statement about the default app. A custom sender can send more, and Shopify’s own settings change over time, including the data sharing levels in the channel app. Open the app’s data sharing screen and read what each level says it sends on the day you set it up, because the level names alone don’t tell you.

Two rows deserve emphasis. Refunds and cancellations don’t reverse a Purchase inside Meta. If your return rate is high, or fraud checks cancel orders after the fact, Meta’s purchase count and value drift upward relative to your books without any error being logged. The other is consent: a server event is easy to send after the shopper said no, because nothing in the browser is left to stop it.

Failure one: why do Purchase events count twice, or refuse to deduplicate?

Duplicate counting is two senders describing one order. Meta merges a browser event and a server event only when they share the same event name and the same event_id. If either differs, Meta treats them as two purchases, and both count.

A real pattern goes like this. A brand installs Shopify’s channel app, which handles its own pairing correctly. Months later an agency adds a server-side tag manager container “to improve match quality”. The container sends its own Purchase with its own generated ID. Now every order arrives from three sources, and only two of them agree with each other. Reported purchases climb, cost per purchase falls, and the media buyer scales spend on an improvement that exists only in the reporting.

The reverse also happens. A team migrates to a new checkout configuration, the browser event stops carrying the ID the server expects, and deduplication silently fails while both copies keep arriving.

How to spot it

Compare purchase counts rather than value. Take one day, count Meta’s reported purchases for the dataset and Shopify’s placed orders for the same day and timezone. If Meta is above Shopify, something is double-sending, because attribution can only claim a subset of orders, never more of them than exist. That single inequality is the fastest test in this article.

Then open Test Events, place a real order, and inspect what arrives. You want one Purchase shown as a browser and server pair, marked deduplicated. Three rows, or two rows with different IDs, is the fault.

The fix

Keep one server sender per dataset. If you need the tag manager container for other destinations, turn off the channel app’s server events, or the reverse. Then confirm the browser event carries the same event_id the server uses. Event names are case-sensitive in practice, so Purchase and purchase are different events.

Failure two: which orders reach Meta that no ad caused?

Phantom orders are quieter. The events are correct, deduplicated and hashed properly, and they’re still the wrong events, because Shopify reports every order and Meta is only supposed to learn from orders that advertising might have influenced.

Consider a subscription brand. A customer buys once from an ad. Every month afterwards, the subscription app creates a new order in Shopify with no browser involved. If your server sender listens to order webhooks, each renewal reaches Meta as a Purchase. Meta’s delivery system then optimises toward whatever profile of person generates lots of purchases, which now includes the dull, predictable pattern of somebody being charged again. Your subscription base isn’t a bad audience. It just isn’t evidence of what the ad achieved. Our note on subscription apps for Shopify covers how the apps create renewal orders, which is the part that matters here.

Point-of-sale orders, wholesale draft orders created by a sales team, exchange orders that replace an item and staff-placed replacements all fall outside advertising influence. None of them is an ad outcome.

Value has its own version of this problem

Purchase value is a second place where the feed and your accounting disagree. Decide, and write down, whether the value sent is before or after discounts, and whether it includes shipping and tax. Meta will use whatever you send, and if the channel app and a custom sender disagree, the same order appears with two values. Refunded and cancelled orders stay in at full value, as the table showed. A brand that fulfils through a slow return cycle will have a wider gap between Meta value and booked revenue than one that doesn’t, and neither figure is wrong.

The fix

Choose, order source by order source, whether it counts. A workable default is that first orders and one-off orders send as Purchase, while renewals, drafts, point of sale and exchanges either don’t send or send under a custom event name that you can still see in reporting. In Shopify, the order’s source and tags give you the filter. If your sender can’t filter, that’s a reason to change senders.

On refunds, there’s no clean native answer. You can hold the Purchase until your return and fraud windows have closed, at the cost of slower learning, or send Purchase immediately and track refunds through a separate custom event that you use in your own reporting. Neither is free. The right one depends on how many orders you reverse, and no published benchmark says what that share is for your category (metric to confirm from your own order data).

Failure three: why does match quality collapse after checkout?

Match-key loss only affects the server path. A browser event has everything: the cookies, the IP address, the user agent, the page. A server event built later from an order record only has what somebody remembered to save.

When Meta receives a server Purchase with a hashed email and nothing else, it has one key to work with. If that email isn’t the one attached to the shopper’s Meta account, the event is unmatched and can’t be credited to an ad. The result is a healthy-looking event stream with weak attribution and, over time, weaker optimisation.

Four values are usually lost:

  • fbc, the click identifier. It is built from the fbclid parameter on the landing URL. The browser Pixel sets the cookie, but a server webhook running minutes later can’t read it unless you stored it. The format is fb. followed by a subdomain index, a creation timestamp and the fbclid.
  • fbp, the browser identifier. It lives in a first-party cookie and has the same problem.
  • Client IP address. A webhook sender sees your server or Shopify’s servers, not the shopper’s device. Sending the wrong IP is worse than sending none, because it looks like a match key but points at nothing.
  • Client user agent. Same cause, same result.

Shopify’s order record carries details about the shopper’s browser, and the fields exposed depend on the API version, so check what yours returns before assuming.

Server events can quietly ignore a consent decision the browser honoured. The Pixel doesn’t fire when the shopper declines, but a webhook sender has no idea unless it reads the customer’s consent state and the marketing preference at order time. Regulations in this area differ between the US states, the UK and the EU, and several of them treat this as a serious matter. Describe your actual data flow to counsel, and don’t rely on the assumption that hashing makes it acceptable.

The fix

Capture the identifiers at landing. A short script on the storefront can write fbclid and the _fbp value onto the cart as attributes. When the order arrives, the sender reads them back from the order’s note attributes. Pass the IP and user agent from the order’s client details when they exist. Use a conservative rule for consent: no marketing consent, no server event for that order. Then watch the event match quality figure for Purchase in Events Manager. Meta publishes no category benchmark, so the useful reading is your own before-and-after.

How do you audit and fix a Shopify Conversions API setup?

Five steps take about an afternoon for a store with a single Meta ad account. They’re ordered so that each one removes noise for the next. Do them in this order, and don’t start with the match-quality score, which is the noisiest number in the account.

Audit which senders fire Purchase

List everything that can post a Purchase to your dataset: the Facebook and Instagram channel app, any tag manager container, any partner tracker, any custom webhook. The evidence is in Events Manager. Open the dataset’s overview and check the sources listed for each event. If two server integrations appear for Purchase, you’ve found failure one before running a single test. Keep one server sender per dataset. Document who owns it.

Give every event one event_id and confirm deduplication

For a fresh test order, the browser event and the server event must share an event_id and an event name. Use the Test Events tab, place a real low-value order with the test code active, and read the parameters on each row. What you want is one Purchase marked as deduplicated. Repeat the check after any theme change, app installation or checkout customisation, because those are the moments it breaks. Our guide to Shopify checkout extensibility explains which parts of checkout your scripts can still reach.

Filter orders no ad caused out of Purchase

Take a week of Shopify orders and group them by source and tag: web, subscription renewal, draft, point of sale, exchange. Mark each group as counts or doesn’t. Implement the rule where the sender builds the event, not in Meta afterwards, because Meta can’t undo a purchase it has received. Keep a note of which orders you excluded. That note is what lets you explain the gap between Shopify and Meta when finance asks.

Carry match keys from landing page to order

Write fbclid and _fbp onto the cart at landing and read them back when you build the server event. Send the real client IP and user agent, not your server’s. Hash email, phone, name and address fields as Meta specifies, after normalising them. Then compare Purchase event match quality before and after. If nothing moves, one of the four values is still missing.

Reconcile Meta against Shopify every week

Put a recurring, boring check in the calendar: Meta’s reported purchase count for the previous full week against Shopify’s placed orders, and Meta’s reported value against booked revenue after refunds. Meta should sit below Shopify on count. A ratio that widens or narrows suddenly after a change is a fault to trace. Connecting the workbook to a proper reporting layer helps, and the Google Analytics on Shopify guide covers the equivalent problem on the other side of your stack.

Who should not build this themselves?

A brand with one sender, no subscriptions and no draft orders can run the channel app’s defaults and spend its effort on creative. That’s a legitimate outcome of the audit, and one a vendor selling implementation won’t tell you.

A brand with a subscription app, wholesale draft orders or a tag manager container already in place has real work to do, because the three failures compound. The refund gap and the renewal problem both push reported results in the flattering direction, which is a bad property in a signal that decides where a paid budget goes. If you spend on Meta and on other channels, you’ll also have to line up how each platform counts purchases before comparing them. The Facebook ads on Shopify and ecommerce PPC pages cover the account-level side.

Nobody here needs a new tool. What helps is one named owner, one sender per dataset, one written definition of “a purchase that counts”, and one weekly reconciliation.

Conversions API health is a paid media problem, and it’s usually a measurement problem before it’s a media one: bidding, budgets and creative tests all read from the same feed, so a fault in it quietly steers every decision downstream. Pointerflow’s paid media service starts from a tracking audit like the one in this article and treats a clean Meta-to-Shopify reconciliation as the entry condition for any spend recommendation. Where measurement questions go beyond Meta, the reporting and analytics service covers the wider set.

Sources

  • No external figures are quoted. The article is written from Meta’s long-documented Conversions API parameters (event name, event_id, action source, customer information parameters, fbc and fbp) and from how Shopify order webhooks and the channel app behave. Check Meta’s developer documentation and the channel app’s data sharing screen for anything dated, including late-event limits.

Frequently asked

Do I still need the Meta Pixel if I use the Conversions API?

For most Shopify stores, yes. Meta's guidance is to run both, browser and server, and let deduplication merge the pairs. The browser side supplies cookies and page context the server can't see. The server side supplies events the browser loses. Dropping the Pixel usually costs you match keys.

Is the Shopify Facebook and Instagram app enough on its own?

It covers the standard shopping events and handles deduplication between its own browser and server copies. It is enough until you add a second sender, need to exclude certain order types, or want events the app doesn't emit. Check its data sharing settings first, then decide whether anything custom is justified.

Can I use the Conversions API without Shopify's own integration?

Yes, through a server-side tag manager container, a partner integration or your own endpoint. You then own deduplication, hashing, consent and retries. Teams do it for control over which orders count. It's a real maintenance commitment, so treat it as a small piece of software with an owner.

Why are Meta's purchases higher than Shopify's orders?

Common causes are duplicate senders that failed deduplication, orders reported twice after an edit, and non-ad orders such as renewals sent as Purchase. Attribution can also credit a purchase to an ad view on a different device. Compare raw purchase counts first, before touching attribution windows.

Why are Meta's purchases lower than Shopify's orders?

Lower is expected: Meta only counts what it can attribute to an ad, and not every order is one. A gap becomes a fault when it widens after a change, or when server events are being rejected. Open the dataset's diagnostics in Events Manager and look for rejected or late events.

What does event match quality actually measure?

Meta scores, per event, how well the customer details you send let it link the event to a Meta account. More and cleaner match keys raise the score. No public benchmark tells you what a good score is for your category, so track your own trend and treat a drop after a release as a regression.

Does the Conversions API get around iOS or browser tracking limits?

It reduces what the browser loses, but it doesn't remove limits on how Meta attributes and uses events. Consent choices and platform privacy rules still apply. Sending data for shoppers who declined marketing tracking is a compliance problem, not a workaround. Confirm your obligations with counsel.

How do I send refunds or cancellations to Meta?

Meta has no automatic reversal of a Purchase when Shopify refunds it. Options are to send Purchase only after your return or fraud window closes, or to send a separate custom event for refunds and use it in reporting. Whichever you pick, document it so the numbers stay comparable.

Should subscription renewals go to Meta as Purchase events?

Usually not. A renewal was not caused by an ad, and reporting it teaches Meta to value the wrong behaviour. Send the first order as Purchase, and either drop renewals or send them under a custom event name. Your subscription app decides how easy that split is.

How do I test the Conversions API without polluting live data?

Use the Test Events tab in Events Manager with the test event code Meta gives you, and place a real low-value test order. Events sent with that code appear in the tab so you can inspect parameters and deduplication before you trust the dataset. Remove the test code from production.

Who should own the setup inside a $3M to $30M brand?

The person who reads the ad account and the person who can change the storefront both need to be in the loop, because a fix usually crosses both. Name one owner, put the weekly reconciliation on their calendar, and require a Test Events check after any theme, checkout or app change.

Next step

Is this your paid media problem, or a symptom of another one?

Bring your numbers — the churn split, the decline rate, whatever your flows are earning — and we will tell you which of them is the expensive one.

Book a call →