If you advertise on Facebook or Instagram, you have probably seen the message in Events Manager: your event match quality is low, or your conversions are being under-reported, or your pixel events are missing customer information. The recommended fix is the Conversions API, usually shortened to CAPI. This article explains what it is, how it works together with the browser pixel, how event de-duplication works, and how to set it up with server-side Google Tag Manager.
The aim is to give you a working mental model, not just a checklist, because most CAPI problems come from misunderstanding how the pieces fit.
What the Conversions API is
The Meta pixel is a script in the visitor's browser that reports events, such as page views, add to cart and purchase, to Meta. It works, but it inherits every browser limitation: blockers, cookie expiry and closed tabs can all prevent an event from arriving.
The Conversions API is Meta's server-to-server alternative. Instead of the browser telling Meta what happened, your server tells Meta directly, over an authenticated connection. Because the connection does not depend on the visitor's browser behaving, the event arrives reliably.
Meta recommends using both together, a setup often called a redundant setup. The pixel provides browser context and immediate signals, and the Conversions API provides reliable delivery. Meta then merges them, which is where de-duplication comes in.
Why it matters for your ads
Meta's delivery system optimises toward the conversion events you send. More complete, better-matched events mean better learning. In particular:
- Recovered events. Purchases that the pixel missed can be reported by the server, so campaigns get closer to the true number of conversions.
- Better matching. The server can send hashed customer details, such as email and phone, that help Meta match the event to a person who saw or clicked an ad.
- Resilience. Optimisation is less exposed to browser tracking limits.
This does not create conversions out of thin air. It improves how many of the real ones Meta can see and attribute.
The key concept: event de-duplication
If the pixel and the Conversions API both report the same purchase, Meta could count it twice. To prevent that, Meta de-duplicates events using two fields:
event_name: for examplePurchase. It must be identical in both versions.event_id: a unique identifier for that specific occurrence. The same ID must be sent by both the pixel and the server for a given purchase.
When Meta receives two events with the same name and the same ID within its de-duplication window, which Meta's documentation describes as roughly 48 hours, it keeps one and discards the duplicate. If the IDs do not match, both count, and your reported conversions inflate. If only the server sends an event, it counts on its own.
How to generate a good event ID
- Create the ID once, in the browser, when the event happens, and send the same value to both the pixel and your server.
- For purchases, the order or transaction ID is a natural choice, since it is unique and known to both sides.
- For other events, generate a random unique string and pass it along with the event.
A frequent mistake is generating the ID separately in the browser and on the server. They will never match, and every event gets counted twice.
Customer information and match quality
Meta uses "customer information parameters" to match server events to Meta accounts. Common ones include email, phone number, first and last name, city, postal code and country, along with the browser identifiers _fbp and _fbc, the client IP address and user agent. Personal details must be normalised and hashed with SHA-256 before sending, as Meta requires, and you should only send what your privacy notice and the visitor's consent allow.
More accurate parameters generally improve match quality, which is the score Meta shows in Events Manager. But do not chase a perfect score by sending data you are not entitled to use. Quality matters more than volume.
The click identifier is worth special mention. When someone arrives from a Meta ad, the URL contains fbclid. The cookie _fbc stores it in a specific format. Passing _fbc with server events lets Meta connect the conversion to the exact ad click. If Safari or a blocker prevented that cookie from being stored, you lose the connection, which is why first-party cookie durability matters here too.
Setting it up with server-side GTM
You can send server events to Meta in several ways, including directly from your store platform or backend. Using a server-side GTM container is popular because it lets you reuse the same incoming event stream for analytics and several ad platforms. The outline is:
1. Have a server-side GTM container running
Create a server container in Google Tag Manager, deploy it and attach a first-party domain. On FlyNode, that means copying your container config, deploying the container and adding your tracking domain.
2. Send events from the browser to your server
In your web container, set the server container URL on your Google tag so events reach the tagging server. Our guide on connecting web GTM to your server container covers it. Make sure the events include the fields you need, such as the event name, value, currency, items and, importantly, a unique event ID.
3. Add the Conversions API tag on the server
In the server container, add a Meta Conversions API tag from the template gallery or a community template, and configure it with your pixel (dataset) ID and an access token generated in Events Manager. Treat that token like a password.
4. Map events and parameters
Configure the tag to map incoming events to Meta's standard events: PageView, ViewContent, AddToCart, InitiateCheckout, Purchase and so on. Pass the event ID, the value and currency for purchases, product identifiers, and the customer information parameters you are permitted to use.
5. Keep the pixel, and match its event IDs
Leave the browser pixel in place, and make its events carry the same eventID you send to the server. Now Meta can de-duplicate.
6. Test
Use Meta's test events tool in Events Manager, with a test event code added to your server tag. Perform a test purchase and check that:
- Both the browser and server events appear.
- They are marked as de-duplicated, with the same event ID.
- The value and currency are correct.
- Customer parameters are received and counted.
Also watch the requests reaching your tagging server in the Event Logs tab, which helps distinguish "the event never reached the server" from "the server sent it but Meta rejected it".
Common problems and fixes
Purchases are double-counted
Event IDs do not match, or event names differ in capitalisation. Confirm both sides send identical event_name and event_id values.
Server events show but with low match quality
You are sending few customer parameters. Add the browser identifiers _fbp and _fbc, the client IP and user agent, and hashed email or phone where you have consent.
Events arrive late
Meta accepts events within a limited time after they occur. Make sure the server forwards events promptly and that timestamps reflect when the event actually happened.
Value or currency missing
Purchase events without a numeric value and a valid currency code are less useful for value-based optimisation. Send a number, not a string with a currency symbol, and a three-letter code such as USD.
Server events fire for visitors who declined consent
The server does not know about the consent choice unless you tell it. Pass the consent state with the event and configure tags to respect it.
Everything works in test but not in production
Check that the production domain matches the one attached to your tagging server, and that the web container containing the server URL setting has actually been published.
Consent and privacy
Using CAPI does not remove your obligations. Personal data sent to Meta needs a lawful basis, and where consent is required, events for visitors who declined should not be sent. Hashing is a security measure, not a way around privacy law. Update your privacy notice to describe the data you share. See server-side tracking and privacy for a fuller discussion.
What results to expect
Set realistic expectations. After a correct setup, most stores see:
- Meta-reported purchases move closer to real orders, since events the pixel missed are now captured.
- Event match quality improves, especially for purchase events.
- Delivery becomes more stable, which can help automated bidding over time.
You should not expect an overnight jump in sales. Better data improves the inputs to optimisation, and gains show gradually. Measure by comparing platform-reported conversions against your shop's real orders before and after, over several weeks. Our guide to reducing ad waste with web analytics shows how to reconcile those numbers.
Checklist
- Server-side GTM container running on your own subdomain.
- Events flowing from the browser to the server with unique event IDs.
- Meta Conversions API tag configured with dataset ID and token.
- Pixel kept, using the same event names and IDs.
- Customer parameters, including
_fbpand_fbc, passed where permitted. - Consent state respected server-side.
- Tested with Meta's test events tool.
- Monitored in your tagging server's logs and in Events Manager.
The bottom line
The Conversions API is not a replacement for the pixel but a partner to it. The pixel gives context, the server gives reliability, and a shared event ID makes sure Meta counts each conversion once. Get those three things right and your campaigns train on a far more complete picture.
If you already run server-side GTM, adding CAPI is mostly a matter of one tag and careful event IDs. If you do not, start with what server-side GTM is and try it on a test container first.
Ready to fix your tracking?
Run server-side GTM on FlyNode: first-party domain, Custom Loader, Cookie Keeper and Event Logs, without managing servers. The Free plan needs no card.
See plans