Est. reading time: 9 minutes
The question usually arrives after a reconciliation. A brand owner compares the order count in their store admin against purchases reported in Ads Manager, finds a spread they cannot explain, asks a developer or an agency about it, and hears that the answer is server-side tracking.
That answer is incomplete in a way that costs money. Server-side tracking is a change to where your tracking requests originate and who controls them. It recovers some of the missing events, changes nothing about others, and introduces a new way to get the numbers wrong.
The accounts we audit tend to split into two groups. Some have no server-side setup and a real reporting gap sitting underneath every budget decision. Others have a server-side setup nobody validated, reporting more purchases than the store recorded orders. Both are fixable, and both start from the same diagnosis.
Where the conversions go missing before Meta ever sees them
Browser-based tracking has three dependencies. A script has to run, an identifier has to persist, and a request has to reach a domain the browser is willing to talk to. All three have narrowed.
WebKit’s tracking prevention documentation is direct about the first two. Safari blocks all third-party cookies by default, with access available only through the Storage Access API. Cookies created in JavaScript, along with LocalStorage, SessionStorage, IndexedDB, and service worker registrations, are deleted after seven days of no user interaction with the site.
Then there is the mechanism that does the most damage to paid social attribution. When Safari detects that a visitor arrived through a decorated link (an ad click carrying a click identifier in the URL) from a domain it classifies as a tracker, it caps the expiry of cookies created in JavaScript on that landing page to 24 hours. The pixel writes the click ID into a first-party cookie, and for a shopper who thinks it over for a few days before buying, that cookie is already gone at the moment of purchase.
Third, some requests never leave. Ad blockers and network-level filtering stop the call outright, and the purchase event specifically fires during a page transition, where an interruption drops it without producing an error anywhere you would look.
Before any of this becomes an engineering project, size it. Take a full month, compare purchases reported in Ads Manager against orders in your store admin for the same window, and hold the comparison to one platform at a time. If the spread is a few percent, the problem is somewhere else. If the platform is reporting well under your order count, you have a signal problem large enough to justify infrastructure spend.
What server-side tracking changes, and what it leaves untouched
Google’s comparison of client-side and server-side tagging describes the architecture plainly. Client-side tagging puts a single container on the site holding every tag, and the browser dispatches an HTTP request to each endpoint it needs to reach. Server-side tagging splits this into two containers. The web container holds only what is needed to record interactions and send them as HTTP requests, and a server container running in a cloud environment you control receives those requests, applies processing rules, and dispatches the vendor-specific calls.
Note the boundary of the claims Google makes for it. The stated benefits are less code executing in the browser, control over what reaches third parties (including removing personally identifiable information before it leaves), and the ability to validate and normalize event data so it meets vendor requirements. When the server container runs in a first-party context on your own domain, site data and cookies stay within your domain and vendors have no third-party cookie access. Defeating blocking is not on that list, because a server container does not do it.
One caveat the vendor pitches skip. Safari detects third-party CNAME cloaking, where a first-party subresource resolves through a CNAME pointing somewhere other than the first-party domain, and caps the expiry of cookies set in that HTTP response to seven days. A tracking subdomain that resolves to someone else’s infrastructure gets treated differently from one that resolves to yours.
The API layer is where the accuracy gain lives. Meta’s Conversions API accepts events from your server, your ecommerce platform, or your CRM, and those server events are linked to a dataset ID and processed the way pixel events are for measurement, reporting, and optimization. A purchase reported from your backend originates in the system that knows the order exists, so it never depends on a browser finishing a page load. Meta is the worked example from here on because that is where the deduplication risk concentrates, and the same logic applies to Google’s enhanced conversions.
Three constraints survive the migration intact. Consent gating still governs collection (Shopify web pixels run in consent-required markets only when the visitor has granted the permissions the pixel is configured to need). A click identifier that was never captured or has already expired cannot be reconstructed on a server. And platform-reported conversions are still attributed by the platform, on its own windows and its own modeling.
Choosing between an app integration, a server container, and a direct backend feed
App or platform integration
Marketing apps install their own pixel through your platform. Shopify’s pixels documentation recommends choosing an app pixel over a custom one where a compatible app exists, on the grounds of higher security and automatic updates. You get the least maintenance and the least control, and the vendor decides which events and parameters get sent. For a brand running one primary paid channel with no developer on call, this is usually the correct stopping point.
A Google Tag Manager server container
Most control, most ownership, a monthly cloud bill for the container itself, and a standing maintenance obligation as platforms change their requirements. On Shopify there is a constraint people discover late. Google Tag Manager can run as a custom pixel, and any pixel Google Tag Manager loads still runs inside Shopify’s sandbox with the same limitations. Sandboxed pixels cannot scrape the DOM, which rules out automatic detection of email addresses, phone numbers, outbound link clicks, and scroll behavior. Every identity parameter has to be passed deliberately out of the event payload.
A direct feed from your backend
Your order system sends the purchase event to the Conversions API when the order is created. This produces the strongest purchase signal available, because no browser is involved, and it covers nothing above the purchase. Most brands spending at volume end up running this alongside one of the other two.
Pick the architecture by asking who maintains it three months from now. A server container that nobody owns degrades into a worse setup than the app pixel it replaced.
Redundant setups double-count until deduplication is configured
Meta recommends running the Conversions API alongside the pixel and calls this a redundant setup. The consequence is that the same purchase arrives twice, and the delivery system needs a way to tell overlapping events from distinct ones. Meta’s deduplication documentation describes two methods for this.
The recommended method matches on event ID and event name. The pixel’s eventID (the fourth argument in the fbq track call) has to match the server event’s event_id, and the pixel’s event has to match the server’s event_name. When the same key combination reaches the same pixel ID within 48 hours, Meta generally keeps whichever event arrived first.
The second method matches on event name plus fbp and/or external_id passed consistently from both sides, and it carries a limitation to understand before choosing it. It generally works only browser-first. A server event will not be discarded if no browser event arrived in the previous 48 hours, even when an identical browser event turns up afterward.
Where this breaks is mundane. One side uses the order ID and the other generates a fresh UUID. Event names differ in capitalization. A retry regenerates the identifier and produces a second unique event. A legacy script left behind in a checkout settings field keeps firing next to the new pixel. None of these produce a warning, and all of them push reported conversions above your real order count, which flatters ROAS in exactly the direction you were hoping to see.
Pick one method, source the identifier from one place (the order ID, for purchases), and confirm that a single test order produces identical strings on both sides before you trust anything downstream.
How to tell whether it worked
Meta treats verification as its own implementation step, confirming that events were received, deduplicated, and matched correctly, and Events Manager holds the screens for it. The Test Events tab shows your test order arriving from both sides with the event IDs visible, which catches a mismatch before it becomes a reporting problem. The event overview reports how many events came from the browser, how many came from the server, and how many were deduplicated. And the Event Match Quality score grades whether the identity parameters you passed deliberately are reaching Meta in a form it can match to a person. A strong purchase feed with a weak match score is still a weak signal.
Then do the equivalent for reporting. Return to the same baseline window you measured before the build, run the same comparison against store orders, and read the direction of the change.
Two outcomes call for different responses. The gap narrows and then holds steady, which is what a working setup looks like. Or the platform begins reporting above your order count, which means deduplication is failing and every number built on top of it is now wrong in the same direction.
Expect attribution to reshuffle rather than expand. Recovered conversions get assigned to the campaigns and ads that were already producing them, so the internal ranking of your campaigns can shift while total revenue sits still. Decisions made in the first week, across a window that spans both configurations, tend to be the wrong ones. Give delivery a full purchase cycle at the new signal quality before you rewrite allocation.
Then set the expectation that matters most. Platform-reported numbers and store orders will never fully agree, because they count different things across different windows under different attribution rules. A stable, explainable gap is the finish line here.
Most brands spending seriously on paid media should do this work, and the payoff is quieter than the pitch suggests. What you get is a set of numbers you can defend in a budget conversation. Start with the reconciliation, choose the architecture from there, and validate deduplication before a single report informs a decision. If you want a second read on the current numbers before scoping the build, we can take a look with you.










