Meta Pixel (formerly Facebook Pixel) enables conversion tracking, audience building, and remarketing for Prismic-powered websites. This guide covers implementation for Next.js, Gatsby, and custom React applications.
Prerequisites
Before you begin:
- Have a Meta Pixel ID from Facebook Business Manager
- Have a Prismic repository set up
- Be using Next.js, Gatsby, or another JavaScript framework
- Have Facebook Business Manager access
Get Your Meta Pixel ID
- Log in to Facebook Business Manager
- Navigate to Events Manager
- Click Connect Data Sources > Web
- Select Meta Pixel
- Copy your Pixel ID (format: 16-digit number)
Method 1: Next.js with Prismic
Step 1: Create Meta Pixel Component
Create components/MetaPixel.js:
'use client';
import Script from 'next/script';
import { useEffect } from 'react';
import { usePathname, useSearchParams } from 'next/navigation';
export default function MetaPixel({ pixelId }) {
const pathname = usePathname();
const searchParams = useSearchParams();
useEffect(() => {
// Track page views on route change
if (typeof window.fbq !== 'undefined') {
window.fbq('track', 'PageView');
}
}, [pathname, searchParams]);
return (
<>
<Script id="meta-pixel" strategy="afterInteractive">
{`
!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', '${pixelId}');
fbq('track', 'PageView');
`}
</Script>
<noscript>
<img
height="1"
width="1"
style={{ display: 'none' }}
src={`https://www.facebook.com/tr?id=${pixelId}&ev=PageView&noscript=1`}
alt=""
/>
</noscript>
</>
);
}
Step 2: Add to Root Layout
In app/layout.js:
import MetaPixel from '@/components/MetaPixel';
import { PrismicPreview } from '@prismicio/next';
const META_PIXEL_ID = process.env.NEXT_PUBLIC_META_PIXEL_ID;
export default function RootLayout({ children }) {
return (
<html lang="en">
<head>
{META_PIXEL_ID && <MetaPixel pixelId={META_PIXEL_ID} />}
</head>
<body>
{children}
<PrismicPreview repositoryName="your-repo-name" />
</body>
</html>
);
}
Step 3: Environment Variables
Create .env.local:
NEXT_PUBLIC_META_PIXEL_ID=1234567890123456
For Next.js Pages Router
In pages/_app.js:
import Script from 'next/script';
import { useRouter } from 'next/router';
import { useEffect } from 'react';
const META_PIXEL_ID = process.env.NEXT_PUBLIC_META_PIXEL_ID;
function MyApp({ Component, pageProps }) {
const router = useRouter();
useEffect(() => {
// Track page views on route change
const handleRouteChange = () => {
if (typeof window.fbq !== 'undefined') {
window.fbq('track', 'PageView');
}
};
router.events.on('routeChangeComplete', handleRouteChange);
return () => {
router.events.off('routeChangeComplete', handleRouteChange);
};
}, [router.events]);
return (
<>
<Script id="meta-pixel" strategy="afterInteractive">
{`
!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', '${META_PIXEL_ID}');
fbq('track', 'PageView');
`}
</Script>
<Component {...pageProps} />
</>
);
}
export default MyApp;
Method 2: Gatsby with Prismic
Step 1: Install Gatsby Meta Pixel Plugin
npm install gatsby-plugin-facebook-pixel
Step 2: Configure gatsby-config.js
module.exports = {
plugins: [
{
resolve: 'gatsby-source-prismic',
options: {
repositoryName: 'your-repo-name',
accessToken: process.env.PRISMIC_ACCESS_TOKEN,
},
},
{
resolve: 'gatsby-plugin-facebook-pixel',
options: {
pixelId: process.env.META_PIXEL_ID,
},
},
],
};
Step 3: Environment Variables
Create .env.production:
META_PIXEL_ID=1234567890123456
PRISMIC_ACCESS_TOKEN=your-access-token
Step 4: Track Custom Events
In gatsby-browser.js:
export const location }) => {
if (typeof window.fbq === 'function') {
window.fbq('track', 'PageView');
// Track preview mode
if (location.search.includes('preview=true')) {
window.fbq('trackCustom', 'PreviewAccess', {
path: location.pathname,
});
}
}
};
Method 3: Custom React Implementation
For vanilla React or other frameworks:
// hooks/useMetaPixel.js
import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
export function useMetaPixel(pixelId) {
const location = useLocation();
useEffect(() => {
// Load Meta Pixel
!(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'
);
window.fbq('init', pixelId);
window.fbq('track', 'PageView');
}, [pixelId]);
useEffect(() => {
if (typeof window.fbq === 'function') {
window.fbq('track', 'PageView');
}
}, [location]);
}
Usage in App:
import { useMetaPixel } from './hooks/useMetaPixel';
function App() {
useMetaPixel('1234567890123456');
return <div>{/* Your app */}</div>;
}
Prismic-Specific Tracking
Track Slice Interactions
// slices/CallToActionSlice.js
'use client';
export default function CallToActionSlice({ slice }) {
const handleCTAClick = () => {
if (typeof window.fbq === 'function') {
window.fbq('track', 'Lead', {
content_name: slice.primary.title,
content_category: 'CTA',
slice_type: slice.slice_type,
});
}
};
return (
<section>
<h2>{slice.primary.title}</h2>
<button
{slice.primary.button_text}
</button>
</section>
);
}
Track Form Submissions
// slices/ContactFormSlice.js
'use client';
export default function ContactFormSlice({ slice }) {
const handleSubmit = async (e) => {
e.preventDefault();
// Track conversion
if (typeof window.fbq === 'function') {
window.fbq('track', 'Contact', {
content_name: slice.primary.form_title,
slice_type: slice.slice_type,
});
}
// Submit form
// ... form submission logic
};
return (
<form
{/* Form fields */}
<button type="submit">Submit</button>
</form>
);
}
Track Document Views by Type
// In your Prismic page component
import { useEffect } from 'react';
export default function PrismicPage({ document }) {
useEffect(() => {
if (document && typeof window.fbq === 'function') {
window.fbq('track', 'ViewContent', {
content_ids: [document.id],
content_type: document.type,
content_name: document.data.title || document.uid,
});
}
}, [document]);
return (
<div>
{/* Render document */}
</div>
);
}
Standard Meta Pixel Events
Purchase Event
For e-commerce Prismic sites:
function handlePurchase(order) {
if (typeof window.fbq === 'function') {
window.fbq('track', 'Purchase', {
value: order.total,
currency: 'USD',
content_ids: order.items.map(item => item.id),
content_type: 'product',
});
}
}
Add to Cart Event
function handleAddToCart(product) {
if (typeof window.fbq === 'function') {
window.fbq('track', 'AddToCart', {
value: product.price,
currency: 'USD',
content_ids: [product.id],
content_name: product.name,
content_type: 'product',
});
}
}
Lead Event
function handleLeadGeneration(formData) {
if (typeof window.fbq === 'function') {
window.fbq('track', 'Lead', {
content_name: formData.formName,
content_category: 'Lead Form',
});
}
}
Custom Events for Prismic
Track Prismic Preview Usage
// components/PrismicPreviewPixelTracking.js
'use client';
import { useEffect } from 'react';
import { useSearchParams } from 'next/navigation';
export function PrismicPreviewPixelTracking() {
const searchParams = useSearchParams();
const isPreview = searchParams.get('preview') === 'true';
useEffect(() => {
if (isPreview && typeof window.fbq === 'function') {
window.fbq('trackCustom', 'PrismicPreviewAccess', {
preview_mode: 'active',
});
}
}, [isPreview]);
return null;
}
Track Slice Zone Engagement
function trackSliceZone(slices) {
if (typeof window.fbq === 'function') {
window.fbq('trackCustom', 'SliceZoneView', {
slice_count: slices.length,
slice_types: slices.map(s => s.slice_type).join(','),
});
}
}
Advanced Match Parameters
Enhance conversion tracking with user data:
// Set advanced matching (if user data available)
if (typeof window.fbq === 'function') {
window.fbq('init', 'YOUR_PIXEL_ID', {
em: 'user@example.com', // Hashed email
fn: 'john', // Hashed first name
ln: 'doe', // Hashed last name
ph: '1234567890', // Hashed phone number
});
}
Note: Always hash personal information before sending to Meta Pixel.
Conversion API Integration
For server-side tracking with Prismic:
Next.js API Route
Create app/api/meta-conversion/route.js:
import { NextResponse } from 'next/server';
export async function POST(request) {
const { event, eventData } = await request.json();
const accessToken = process.env.META_CONVERSION_API_TOKEN;
const pixelId = process.env.NEXT_PUBLIC_META_PIXEL_ID;
const response = await fetch(
`https://graph.facebook.com/v18.0/${pixelId}/events`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
data: [{
event_name: event,
event_time: Math.floor(Date.now() / 1000),
user_data: {
client_ip_address: request.headers.get('x-forwarded-for'),
client_user_agent: request.headers.get('user-agent'),
},
custom_data: eventData,
}],
access_token: accessToken,
}),
}
);
const result = await response.json();
return NextResponse.json(result);
}
Client-side usage:
async function trackServerSide(event, data) {
await fetch('/api/meta-conversion', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ event, eventData: data }),
});
}
Testing & Validation
1. Meta Pixel Helper Chrome Extension
- Install Meta Pixel Helper
- Visit your Prismic site
- Click the extension icon
- Verify Pixel is detected and events fire
2. Events Manager Test Events
- Go to Events Manager > Test Events
- Enter your browser identifier or IP
- Interact with your site
- See events appear in real-time
3. Browser Console Testing
// In browser console
console.log(window.fbq);
console.log(window._fbq); // Should show Meta Pixel object
// Test event manually
fbq('track', 'Lead', { test: true });
Common Issues & Solutions
Issue: Pixel Not Loading
Cause: Ad blocker or script not loaded
Solution: Test in incognito mode without extensions
Issue: Events Not Firing on Route Change
Cause: SPA navigation not tracked
Solution: Use route change listener (see Next.js example above)
Issue: Duplicate Events
Cause: Multiple Pixel initializations
Solution: Ensure Pixel component only rendered once in root layout
Issue: Preview Mode Events Not Tracked
Cause: Pixel excluded from preview
Solution: Don't exclude preview routes from Pixel loading
Privacy & Compliance
GDPR Consent
Implement consent before loading Pixel:
'use client';
import { useState, useEffect } from 'react';
import MetaPixel from './MetaPixel';
export function ConsentAwareMetaPixel({ pixelId }) {
const [consent, setConsent] = useState(false);
useEffect(() => {
// Check consent (use your consent management platform)
const hasConsent = localStorage.getItem('cookie-consent') === 'true';
setConsent(hasConsent);
}, []);
if (!consent) return null;
return <MetaPixel pixelId={pixelId} />;
}
Disable Automatic Advanced Matching
fbq('init', 'YOUR_PIXEL_ID', {
autoConfig: false,
enableAutomaticMatching: false,
});
Next Steps
- Configure GTM for Prismic for centralized tag management
- Set up Prismic GTM Data Layer
- Troubleshoot Events Not Firing