meta-pixel-react
v0.1.0
Published
React bindings for meta-pixel: an SSR-safe provider and hooks for Meta's Pixel.
Maintainers
Readme
meta-pixel-react
React bindings for
meta-pixel: an SSR-safe provider and a typed hook for Meta's Pixel. Client-side only.
Why
Most React pixel wrappers expose a singleton you must init yourself in an effect, drop window is undefined errors during SSR, and accept untyped track(event, data) calls. This package gives you:
<MetaPixelProvider>— loadsfbevents.jsand initializes your pixels on the client only (safe to render during SSR/RSC).useMetaPixel()— a typed hook;Purchaserequirescurrency/value, advanced-matching fields are strings, etc. (all inherited frommeta-pixel).- Automatic
PageViewon route change, glob-matched per pixel. - GDPR consent helper for the revoke-then-grant flow.
Installation
npm i meta-pixel-react
# react >= 18 is a peer dependencyUsage
Wrap your app once. Pass the current pathname from your router to get automatic page views:
import { MetaPixelProvider } from 'meta-pixel-react'
const pixelOptions = {
consent: 'revoke', // optional: hold delivery until the user opts in
pixels: {
main: { id: '1234567890', pageView: '**' },
},
} as const
export function App({ children }: { children: React.ReactNode }) {
const pathname = usePathname() // next/navigation, react-router, etc.
return (
<MetaPixelProvider options={pixelOptions} pathname={pathname}>
{children}
</MetaPixelProvider>
)
}Define
optionsoutside the component (oruseMemoit) — it is read once on mount.
Next.js (App Router)
<MetaPixelProvider> is a Client Component ('use client'), so wrap it in your own client providers file and mount it in the root layout. usePathname() drives the automatic PageView:
// app/providers.tsx
'use client'
import { usePathname } from 'next/navigation'
import { MetaPixelProvider } from 'meta-pixel-react'
const pixelOptions = {
pixels: { main: { id: '1234567890' } },
} as const
export function Providers({ children }: { children: React.ReactNode }) {
const pathname = usePathname()
return (
<MetaPixelProvider options={pixelOptions} pathname={pathname}>
{children}
</MetaPixelProvider>
)
}// app/layout.tsx (Server Component — no 'use client')
import { Providers } from './providers'
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<Providers>{children}</Providers>
</body>
</html>
)
}The provider is safe to render on the server: fbevents.js is only injected in a client effect, so SSR/RSC never touches window/document.
Pages Router: pass
pathname={router.asPath.split('?')[0]}fromnext/router'suseRouter()instead ofusePathname().
Track events
Track events anywhere below the provider:
import { useMetaPixel } from 'meta-pixel-react'
function CheckoutButton() {
const { $fbq } = useMetaPixel()
return (
<button onClick={() => $fbq('track', 'Purchase', { value: 9.99, currency: 'EUR' })}>
Buy
</button>
)
}GDPR consent
Configure consent: 'revoke' to hold delivery, then grant once the user accepts:
const { consent } = useMetaPixel()
// in your cookie-banner accept handler:
consent('grant')Manual page views
Omit pathname to disable automatic page views and fire them yourself:
const { pageView } = useMetaPixel()
pageView() // every pixel
pageView('1234567890') // a single pixel (uses trackSingle)API
<MetaPixelProvider options pathname?>
| Prop | Description |
| --- | --- |
| options | { enabled?, consent?, pixels }. Read once on mount. |
| pathname | Current route path. When it changes, pixels whose pageView glob matches fire a PageView. Omit to disable auto page views. |
options.pixels is keyed by an arbitrary name; each pixel is { id, autoConfig?, advancedMatching?, pageView? }. enabled: false loads and sends nothing while keeping useMetaPixel() working (no-op $fbq).
useMetaPixel()
Returns { $fbq, consent, pageView }. $fbq is the fully-typed query function from meta-pixel — use it for track, trackCustom, trackSingle, and CAPI deduplication via the 4th eventID arg: $fbq('track', 'Purchase', {...}, { eventID }).
pageView globs
Patterns use meta-pixel's in-house matcher: **, *, ?, and a leading !. No brace/char-class expansion.
Resources
- Core library: https://npmjs.com/package/meta-pixel
- Pixel reference: https://developers.facebook.com/docs/meta-pixel/reference
- Advanced matching: https://developers.facebook.com/docs/meta-pixel/advanced/advanced-matching
