Fireshift / Guides

Meta Pixel firing before cookie consent: how to check and fix it

By Nurkan Kirkan, growth & analytics consultant · Updated 2026-11-04

Short answer

Clear cookies, load your site, and don't touch the banner. If DevTools shows requests to facebook.com/tr, or a _fbp cookie appears, the pixel is running before consent. The usual causes: the pixel tag fires on All Pages in GTM with no consent check, the pixel is hardcoded in the site template or added by a plugin, or the banner records the choice without blocking tags. Fix: fire the pixel only after the consent event, or call fbq('consent', 'revoke') before fbq('init') and fbq('consent', 'grant') on accept.

How to check in 3 minutes

  1. Open a private window (no cookies from earlier visits).
  2. Open DevTools → Network before loading the page. Filter on facebook.
  3. Load your homepage. Do not click the banner. Visit a second page.
  4. Look for requests to connect.facebook.net/…/fbevents.js (the script) and www.facebook.com/tr (the events, usually ev=PageView).
  5. Check DevTools → Application → Cookies for _fbp.
  6. Now reject cookies and repeat. Nothing should reach facebook.com/tr after a reject either.

The script loading matters less than the /tr hits. With Meta's consent API the script can load while sending nothing. No /tr requests and no _fbp before accept is the result you want.

Why it happens

  • GTM tag on All Pages with no consent condition. A Custom HTML tag with the pixel base code on the All Pages trigger runs before the banner gets a say.
  • Google Consent Mode is set up, but Meta is not a Google tag. Consent Mode changes how Google tags behave. A Custom HTML Meta tag ignores it unless you add a consent requirement to the tag in GTM (Advanced settings → Consent settings → require ad_storage) or fire it from a consent trigger.
  • Hardcoded pixel. Someone pasted the base code into the theme, or a Shopify app or WordPress plugin added it. The banner has nothing to block.
  • Two pixels. One in GTM behind consent, one hardcoded without it. The consent setup looks right and the leak continues.
  • A banner that only displays. Some banners collect the choice but block nothing until they are wired to the tags.

How to fix it

  1. Find every copy of the pixel. Search the page source for fbq( and fbevents.js, and check GTM for Custom HTML and template tags that load it. Remove the duplicates.
  2. Gate it in GTM. Either fire the pixel on a custom event your banner pushes on accept, or add a consent requirement for ad_storage in the tag's consent settings. Your banner must update consent state for the second option to work.
  3. Or use Meta's consent API. Call fbq('consent', 'revoke') before fbq('init', '…'). When the visitor accepts, call fbq('consent', 'grant'). Events are held back until grant.
  4. Retest in a fresh private window three ways: accept, reject, ignore the banner. Only the accept path should reach facebook.com/tr.

What it costs

In the EU and UK, marketing pixels generally need prior consent, and regulators have fined sites for setting tracking cookies before it. Elsewhere the risk is lower, but a banner that blocks nothing is a promise you aren't keeping. This is not legal advice; your privacy counsel decides what each market needs.

The fix lowers the events Meta receives. That is expected. If you also run Conversions API from your server, it has to respect the same choice, and nobody can check that from outside, us included.

FAQ

Does Google Consent Mode cover the Meta Pixel?

No. Consent Mode controls Google tags. A Meta Pixel in GTM needs its own consent condition or a trigger that only fires after accept.

Is loading fbevents.js before consent a leak?

The request sends the visitor's IP address and browser details to Meta, so some reviewers count it. The bigger issue is /tr event hits and the _fbp cookie. The safest setup loads nothing until accept.

Run all nine checks on your site, free.

Fireshift reads what your site tells Google Ads, GA4 and Meta from the outside. No install, about a minute.

Get my Leak Score