Cloud VPS

Facebook Pixel vs Conversions API (CAPI): What's the Difference and Why Use Both

Updated 2026-09-21~10 min read

The Facebook Pixel is the tracking code almost every advertiser installs on their site so Meta knows who visited, who placed an order, and which ads actually drove sales. But over the past few years, more and more Pixel-only data has gone missing, due to ad blockers, browser privacy settings and restrictions on iOS devices.

That is why Meta offers the Conversions API, or CAPI, which sends the same events from your server directly to Meta. This article explains how the Facebook Pixel and the Conversions API differ, why Meta recommends using both, how to set up deduplication so sales aren't counted twice, and which server-side setup method suits whom.

What is the Facebook Pixel and how does it work?

The Facebook Pixel (now called the Meta Pixel) is a piece of JavaScript placed on your web pages. When a visitor opens a page, their browser loads this code and sends events back to Meta, such as PageView, ViewContent, AddToCart, Lead or Purchase, along with supporting data like order value and currency.

This data is used in three ways: to measure which campaigns generate conversions, to teach the ad system what kind of people to show ads to, and to build retargeting audiences, such as people who added to cart but haven't paid.

The key point is that all of this happens in the browser. The Pixel only works if the user's browser agrees to load the script and send data out. If anything blocks it along the way, that event simply disappears without you knowing.

If you are new to advertising, read the basics in How to run Facebook ads. And because the Pixel runs on your own web pages, the quality of your destination page matters just as much — see What is a landing page.

Why the Pixel alone doesn't capture everything

Browser-side tracking has structural weaknesses; it isn't a matter of installing it wrong. Even if every line of code is placed correctly, some data will still be lost for these reasons.

  • Ad blockers and privacy extensions — many block Meta's script from loading at all, so events from these users are never sent.
  • Browser tracking prevention — Safari has Intelligent Tracking Prevention (ITP), and other browsers have similar features that limit the lifetime of cookies set by JavaScript, making it harder to link an ad click to a purchase made days later.
  • iOS tracking permission — since Apple added the prompt asking permission to track across apps, many users choose not to allow it, so Meta has less data to match users with.
  • Dropped connections or closing the page early — a user pays and closes the tab before the thank-you page finishes loading, so the Purchase event is never sent.
  • Cookie consent — if your site has a consent banner and the user declines, the Pixel shouldn't run in the first place.
💡 How much data goes missing varies hugely by audience, device and type of site. There is no single figure that applies to every site. The best approach is to compare the numbers in Events Manager with the actual orders in your own back-end system.

What is the Conversions API (CAPI) and how is it different from the Pixel?

The Conversions API lets your server send events directly to Meta, server to server, without going through the user's browser. When an order is placed in your back-end system, your server can fire the Purchase event to Meta straight away, so browser ad blockers have no effect on this channel.

Another advantage is that you can send data the browser doesn't have, such as orders with confirmed payment, leads your sales team has verified as good quality, or cancelled orders. That brings the data the ad system learns from closer to your real sales.

But CAPI doesn't replace the Pixel. The Pixel sees on-page behaviour the server can't, such as browsing products, and has Meta's cookies in the browser to help match users. That is why Meta recommends using both together and letting the system discard duplicate events.

TopicFacebook PixelConversions API
Sends data fromThe user's browserYour server
Affected by ad blockersYesDoesn't go through the browser, so it isn't blocked there
SetupPaste code on the site, quick to doNeeds a plugin, gateway or server-side code
Data it can sendOn-page behaviourBack-end events, such as confirmed payments
User matchingUses Meta's cookies in the browserUses hashed customer data + forwarded fbp/fbc

Using both means setting up deduplication with event_id

When both the Pixel and CAPI send the same Purchase event, sales will be counted twice unless you tell Meta they are the same event. Your reports will look better than reality, and the ad system will learn from wrong data.

Meta's recommended method is to send the same event ID from both sides. On the Pixel side, put eventID in the fourth parameter of the fbq track call; on the CAPI side, set event_id. The values must match, and the event names must match too: the Pixel's event must equal the CAPI event_name, for example Purchase on both.

According to Meta's documentation, if it receives events with a matching event_id and event_name pair from the same Pixel within 48 hours, it keeps one and discards the duplicate. In practice this ID is often the order number, or a random value generated when the user clicks the button, with the same value passed to both the page code and the server.

💡 Meta also has a fallback deduplication method based on event_name combined with fbp or external_id, but it has more limitations. The primary method you should always use is event_id with event_name.

Event Match Quality and hashing customer data

Events sent through CAPI are only useful if Meta can match them to a user. Events Manager shows an Event Match Quality score indicating how well the customer data you send helps with matching. The more correct parameters you send, the higher the score.

Personal data such as email, phone number, first name, last name, city, postcode and external_id must be normalised first, then hashed with SHA-256. For example, emails must have leading and trailing spaces trimmed and be converted to lowercase. Phone numbers must contain digits only, with the leading zero removed and the country code added, so the Thai number 081-234-5678 becomes 66812345678 before hashing.

Some data must be sent unhashed: client_ip_address, client_user_agent, fbp (the _fbp cookie that identifies the browser) and fbc (the value derived from fbclid when the user clicks an ad). For website events, Meta requires client_user_agent to be sent as well.

  • em, ph, fn, ln, ct, zp, country, external_id — normalise, then hash with SHA-256.
  • client_ip_address, client_user_agent — send the real values unhashed, taken from the user's request.
  • fbp, fbc — read from the user's cookies and forward unhashed; this helps server-side events match browser-side events more accurately.
💡 On consent: sending customer data to an ad platform is processing personal data. In Thailand, you should consider the Personal Data Protection Act (PDPA), for example by disclosing it in your privacy policy and asking for cookie consent before enabling marketing tracking. Hashing reduces the risk but doesn't make the issue go away. For specifics that apply to your business, consult a legal professional.

How many ways are there to set up the Conversions API, and which should you choose?

There is no single best method for everyone. It depends on what your site is built with, whether you have a developer on the team, and how much control you want over your data. This table summarises the four main options.

MethodBest forProsLimitations
Platform plugin or integration, such as Shopify or the Facebook for WooCommerce pluginStores on off-the-shelf platformsSet up in a few clicks, no extra server neededLimited event customisation, depending on what the plugin supports
Meta's Conversions API GatewayBusinesses without a developer that want full CAPISet up through Events Manager, built-in deduplication, updates itselfMust run on a supported cloud account (AWS or GCP) or through a partner; not designed for a general VPS
Server-side Google Tag Manager on your own serverSites already using GTM that want to send data to several platformsManage Meta, GA4 and other tags in one place; data passes through your own domain firstYou need to set up a server and an HTTPS subdomain, and maintain them yourself
Calling the API directly from your back endCustom-built sites with a developerThe most control over data; send any kind of back-end eventYou write and maintain the code yourself, including hashing, deduplication and error handling
💡 If you use Shopify or WooCommerce, always start with the platform's official integration, and only move to a more complex method when you hit a real limitation.

Where a VPS comes in, and what spec you need

Example: sending an event with curl

The last two methods in the table need a server that is always on and has HTTPS. If the server goes down, all CAPI events during that time are lost. This is where a VPS helps.

For self-hosted server-side GTM, Google has a manual setup guide that lets you run the tagging server as a Docker image on a machine of your choice. You need both a tagging server and a preview server, with an HTTPS subdomain of your site pointing to them. Google says each instance shouldn't exceed 1 vCPU, since extra vCPUs aren't used, and recommends running a cluster when traffic is high. For small to medium sites, a VPS with 2 vCores / 4 GB RAM runs both comfortably along with a reverse proxy.

If you write your own endpoint that receives events and forwards them to Meta, the workload is very light, and even the smallest VPS can handle it if traffic isn't high. You should still have a queue or retries in case Meta responds slowly. As for the Conversions API Gateway, Meta's documentation says it must run on an AWS or GCP account, so it isn't an option for a general VPS.

Running sGTM or your own endpoint with Docker makes moving servers and updating much easier. To see what else a VPS can do for advertising work, read VPS for media buyers.

  • Send a POST request to https://graph.facebook.com/vXX.0/PIXEL_ID/events, replacing vXX.0 with the Graph API version you use, and include an access_token generated in Events Manager.
  • Example command: curl -X POST "https://graph.facebook.com/vXX.0/PIXEL_ID/events?access_token=TOKEN" -H "Content-Type: application/json" -d @event.json
  • In event.json, set data to an array of events. Each one has event_name, event_time (a Unix timestamp in seconds), event_id, action_source set to website, event_source_url, and user_data containing hashed em, client_ip_address, client_user_agent, fbp and fbc.
  • While testing, add test_event_code at the top level of the payload, then remove it before going live.
💡 Keep the access_token in an environment variable or a config file that isn't in public code. Never embed it in a web page, because anyone who gets the token can send fake events to your Pixel.

Testing with Test Events, and common mistakes

Once setup is done, go to Events Manager, select your Pixel and open the Test events tab. For the Pixel, open your site through the test field and perform real actions. For CAPI, copy the test code into test_event_code in your payload. Events appear almost instantly, showing whether they came from the browser or the server and whether they were deduplicated.

If you see the same event arrive from both sides and the system says it was deduplicated, your event_id is set up correctly. After that, check the Event Match Quality score on the overview page once real data has been coming in for a while.

MistakeConsequenceFix
Sending from both Pixel and CAPI with no event_id, or mismatched valuesConversions double counted, inflated reportsUse the same event_id on both sides and make event names match exactly
Sending email or phone numbers unhashedPersonal data risk, and matching doesn't work as it shouldNormalise, then hash with SHA-256 before every send
Hashing IP, user agent, fbp or fbcMeta can't use these values for matchingSend these four values unhashed
event_time in milliseconds, or using send time instead of when the event actually happenedEvents rejected or timestamps skewedUse a Unix timestamp in seconds for when the event actually happened, no older than 7 days
Forgetting to remove test_event_code in productionEvents show up in the test view, causing confusion when checkingKeep test and production configuration clearly separate
Sending server events regardless of cookie consentContradicts what you told usersMake the server side respect the same consent status as the browser side
💡 Meta's documentation states that if any event in a request has an event_time older than 7 days, the whole request is rejected. If you send in batches, filter out old events first.

Want to run server-side GTM or a CAPI endpoint on your own machine?

Cloud VPS in a Bangkok datacenter · Windows or Linux · KVM with full root access · runs Docker · extra IPv4 at 100฿ per IP · from 150฿/month

Frequently Asked Questions

What is the Facebook Pixel?

The Facebook Pixel, or Meta Pixel, is JavaScript placed on your site that sends events such as page views, add-to-carts and purchases from the user's browser to Meta. It is used to measure ad results, help the ad system learn, and build retargeting audiences.

If I have the Conversions API, do I still need the Pixel?

You should use both. Meta recommends sending events from both the Pixel and the Conversions API and setting up deduplication with event_id and event_name, because each side sees different data. The Pixel sees on-page behaviour, while CAPI can still send when the browser is blocked.

Do I need to write code to set up the Conversions API?

Not always. If you use Shopify or WooCommerce, there are official integrations you can enable from the settings, or you can use Meta's Conversions API Gateway, set up through Events Manager on an AWS or GCP account. But if your site is custom-built and you want fine control over data, calling the API from your back end or using server-side GTM is more flexible.

What data do I need to hash before sending?

Personal data such as email, phone number, first name, last name, city, postcode, country and external_id must be normalised and hashed with SHA-256. client_ip_address, client_user_agent, fbp and fbc must be sent unhashed.

What VPS spec do I need to run server-side GTM?

Google says each tagging server instance shouldn't exceed 1 vCPU, since anything beyond that isn't used. For small to medium sites, a VPS with 2 vCores / 4 GB RAM comfortably runs the tagging server and preview server in Docker along with a reverse proxy. If traffic gets very high, split across several machines, and base your decision on actual resource usage.