When a Meta pixel is not firing, the cause is almost always one of six things: the pixel ID was never set in the site's environment on the host, a consent banner is blocking the script, an ad blocker or browser tracking prevention is dropping the request, the base code loads after the event it is supposed to catch, two pixels are installed and fighting, or the Lead or Purchase event is simply never called on the thank-you step. You confirm which one with Meta Events Manager Test Events, the browser network tab, and the Pixel Helper extension, then you close the gap permanently with the Conversions API. This piece walks the diagnosis top to bottom, explains the server-side half, and covers domain verification, Aggregated Event Measurement and the audience check that tells you tracking is alive.
The Meta pixel is a JavaScript snippet that loads a script from Meta on every page of your site and sends a request to Meta's tracking endpoint for each page view and each event you call, so Meta can attribute conversions to ads and build audiences from visitors. The Conversions API is the server-side counterpart: your server sends the same events to Meta directly over HTTPS, with an event ID that lets Meta deduplicate against the browser event when both arrive.
The six causes we find most often.
We run these audits on our own stores and on accounts we take over, and the distribution is boringly consistent.
- Pixel ID never set on the host: the theme or template references an environment variable or a theme setting, it was set locally or on staging, and production renders the init call with an empty string
- Consent banner blocking the script: the consent management platform categorizes the pixel as marketing and withholds it until the visitor accepts, and many visitors never click accept
- Ad blockers and browser tracking prevention: the browser drops the request to Meta's script host or tracking endpoint, which you cannot fix client-side and which is the main reason the Conversions API exists
- Base code loading after the event: the Purchase event is called in checkout code that runs before the pixel script has initialized, so the call goes nowhere
- Duplicate pixels: one from the platform integration and one pasted into the theme, producing double page views and inflated conversions
- Standard event never called: the thank-you or confirmation step renders without any Purchase or Lead call, often because the confirmation page belongs to a different template or a third-party checkout
How to verify whether the pixel is firing.
Do not trust the theme settings screen. Look at what actually leaves the browser. Three checks, in this order.
Events Manager Test Events. In Meta Events Manager, select the pixel, open the Test Events tab, enter your site URL and open it. Browse a page, add to cart, complete a test order. Each event should appear within seconds with its parameters. If nothing appears on page load, the base code is not running at all.
The browser network tab. Open developer tools, go to Network, and filter on tr. Every pixel event is a request to the facebook.com/tr endpoint with query parameters: id is the pixel ID, ev is the event name, and the cd parameters carry value and currency on a purchase. An empty id parameter is the missing environment variable. No tr requests at all means the script never loaded or was blocked.
The Pixel Helper extension. Install it in Chrome, load the page, and click the icon. It lists every pixel it finds, the events fired, and warnings such as duplicate pixel IDs or events fired before initialization. It is the fastest way to spot two pixels on the same page.
Diagnose top to bottom.
This is the order we run. Each step isolates one layer so you stop at the first real failure.
Conversions API: the server-side half.
The Conversions API sends events from your server to Meta over HTTPS with a system user access token. It is not a replacement for the pixel; it is the second copy that arrives when the browser copy is blocked. The two are reconciled with the event ID: the browser sends the Purchase event with an eventID such as the order number, and the server sends the same event name with event_id set to the same value. Meta keeps one. Without a shared event ID you double count every conversion that gets through both paths.
There are three ways to set it up, and which one we choose depends on the platform.
| Route | Best for | Setup effort | Deduplication | What usually breaks |
|---|---|---|---|---|
| Partner integration (Shopify, HubSpot, WooCommerce plugin) | Stores on a supported platform with a standard checkout | Low: connect the account and enable server events | Handled by the integration when the browser pixel is also theirs | A second pasted pixel that does not share the integration's event IDs |
| Tag manager server container | Sites already on Google Tag Manager with a data layer | Medium: a server container, a custom subdomain, and a Meta tag in it | You pass the same event ID from the web container to the server tag | The server container running on a subdomain that blockers learn to block |
| Small server function with the access token | Custom stacks, lead forms, offline or delayed conversions | Medium to high: code, token storage, error handling | You generate the event ID and send it to both browser and server yourself | Token stored in client code, missing user data hashing, silent failures with no retry |
Whichever route, the server event needs the customer information parameters Meta uses for matching: hashed email, hashed phone, client IP address, user agent, and the fbp and fbc cookie values when available. Events Manager shows an event match quality score per event; a low score means conversions are arriving but Meta cannot tie them to the person who clicked.
The wiring is the same discipline we describe in our conversion tracking audit checklist, applied to one platform.
Domain verification and Aggregated Event Measurement.
Two account-level settings block conversions from counting even when the pixel is perfect. First, verify your domain in Business Settings under Brand Safety and Suitability, then Domains, by adding the meta tag or the DNS record. Second, in Events Manager open Aggregated Event Measurement and configure the web events for that domain: choose the conversion events you optimize for and rank them by priority, with Purchase above Add to Cart above View Content for a store, or Lead at the top for a lead-generation site.
If the domain is unverified or the event is not in the configured list, campaigns optimizing for that event will report poorly for browsers that limit tracking, and you will wonder why the pixel looks fine but the ads do not learn. The setting is easy to miss because it sits outside the pixel code entirely.
The smoke test: audience sizes.
Before any code review, open Audiences in Ads Manager and look at the size of your website visitors audience for the last 30 days. If it is empty or shows an error, the pixel has been silent for a month. If it is a small fraction of your analytics sessions, it is firing on some pages or for some visitors only, which points at consent or load order. Retargeting audiences fill only from pixel and Conversions API events, so their size is the plainest signal you have that tracking is alive.
We check this weekly on every account we manage under paid media, because a retargeting campaign running against an empty audience spends nothing and reports nothing, and that silence is easy to mistake for a creative problem. It is also the first thing we look at when someone asks what a Facebook ads agency does now: before creative, before bidding, we make sure the account can see.
“A pixel that fires on staging and not on production is the most common tracking bug on the internet, and it takes thirty seconds to find if you look at the page source instead of the settings screen.”
Mistakes that keep the pixel silent.
- Setting the pixel ID on staging and never on production, then testing on staging and declaring it fixed
- Installing the platform integration and a pasted snippet, doubling every event and then disabling the wrong one
- Sending Conversions API events without event IDs, so browser and server copies both count and reported purchases exceed real orders
- Placing the Purchase event on the checkout page instead of the confirmation page, which fires for everyone who starts and never finishes
- Skipping domain verification and Aggregated Event Measurement, so the events arrive but the campaigns cannot optimize on them
- Never looking at audience sizes, which would have revealed the outage the week it started
How do I know if my Meta pixel is working?
Open Meta Events Manager, select the pixel, and use the Test Events tab with your site URL while you browse and complete a test conversion. Confirm events appear with the right names and values. Then open your browser's network tab, filter on tr, and check that the requests carry your pixel ID. Finally, check that your website visitors audience in Ads Manager is growing.
Why does the Pixel Helper show an error but events still appear?
The Pixel Helper flags conditions such as duplicate pixel IDs, events fired before initialization, or missing parameters. Events can still reach Meta in those states, but they may be double counted or lack value data. Treat each warning as a real defect: remove duplicate installs, move event calls after the base code, and pass value and currency on Purchase events.
Do I still need the pixel if I set up the Conversions API?
Yes. Meta recommends running both. The pixel captures browser context such as the fbp and fbc cookies that improve matching, and the Conversions API captures conversions the browser copy misses because of blockers or tracking prevention. Deduplicate them with a shared event ID on each event so the same purchase is never counted twice.
What is the fastest way to set up the Meta Conversions API?
If your store runs on Shopify, enable it through the Facebook and Instagram sales channel, which sends both browser and server events with matching IDs. HubSpot and WooCommerce have similar partner integrations. Custom sites use a Google Tag Manager server container or a small server function calling the Conversions API with a system user access token and a generated event ID.