Consenti

Meta Pixel & Conversions API

Meta Pixel ships its own runtime consent flag (fbq('consent', …)) — so instead of gating the whole script, the usual pattern is to load the pixel once and let it sit revoked until Consenti tells it otherwise. This guide covers both the browser Pixel and what to check before forwarding events to the server-side Conversions API (CAPI).

Reading consent in Meta's shape

typescript
const metaConsent = widget.getConsent('meta')
// {
//   pixel: 'denied',           // Meta Pixel base tracking — from cookies with purpose: 'marketing'
//   api: 'denied',             // Conversions API forwarding — from cookies with purpose: 'marketing'
//   plugins: 'granted',        // Social plugins (Like/Share buttons) — from cookies with purpose: 'functional'
//   facebookLogin: 'granted',  // Facebook Login button — from cookies with purpose: 'functional'
// }
ℹ️pixel and api both roll up from the same marketing purpose — Meta doesn't distinguish client vs. server tracking consent, so treat them as one signal unless you've split them into separate cookie parameters. See API Methods for the full getConsent(type) reference.

Step 1 — Load the pixel revoked by default

Load the standard Pixel base code once, but call fbq('consent', 'revoke') immediately after init so no events send until Consenti grants marketing consent:

meta-pixel.html
html
<script>
!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,
document,'script','https://connect.facebook.net/en_US/fbevents.js');

fbq('init', 'YOUR_PIXEL_ID');
fbq('consent', 'revoke');   // start denied — Consenti flips this once consent exists
fbq('track', 'PageView');   // safe to call even while revoked; fbq queues but withholds the send
</script>

Step 2 — Sync the consent flag from Consenti

CategoryAction's id is your own authored category ID (see Category type) — use whichever one covers marketing/advertising consent in your profile; 'marketing' below is just the common convention:

meta-pixel.ts
typescript
import { CategoryAction } from '@consenti/ui'

new CategoryAction({
  id: 'marketing',
  widget,
  onGrant: () => fbq('consent', 'grant'),
  onDeny: () => fbq('consent', 'revoke'),
})

CategoryAction evaluates immediately at construction (so a returning visitor who already consented gets fbq('consent', 'grant') without waiting for a new submission) and re-fires on every future consenti:consentSubmitted event — including revocations from the preference modal.

💡If you'd rather not load fbevents.jsat all for visitors who've never consented, wrap the whole snippet in a CategoryScript instead (categoryId: 'marketing', unsafeInnerHTML containing the block above minus the consent('revoke')call). The tradeoff: first-time visitors who accept won't have historical pre-consent pageviews for Meta's attribution modelling, since the script never ran at all.

Server-side: Conversions API

CAPI calls happen from your backend, so Consenti's browser-side flag can't gate them directly — check api before you even construct the payload you send to your server:

typescript
const metaConsent = widget.getConsent('meta')

if (metaConsent?.api === 'granted') {
  await fetch('/api/track-purchase', {
    method: 'POST',
    body: JSON.stringify({ event: 'Purchase', value: 49.99, currency: 'USD' }),
  })
}
// Your backend route then calls the Graph API Conversions API endpoint.
// Meta recommends also passing the visitor's Pixel consent status upstream
// so Meta's own systems can apply Limited Data Use processing where required.

Verifying

  1. Install the Meta Pixel Helper browser extension.
  2. Before consenting, the extension should show the pixel as loaded but firing events with a consent-denied indicator (no data actually sent).
  3. Accept marketing consent on the Consenti banner.
  4. Confirm a PageView(or your next tracked event) now appears in Events Manager's Test Events tool within a few seconds.

Frequently asked questions