Installing Meta Pixel on Sitecore
This guide covers implementing Facebook Meta Pixel (formerly Facebook Pixel) on Sitecore websites for conversion tracking, retargeting, and advertising optimization across traditional MVC and headless JSS implementations.
Prerequisites
Before installing Meta Pixel on Sitecore:
Create Meta Pixel
- Go to Facebook Events Manager
- Create a new Pixel
- Copy your Pixel ID (format: 15-16 digit number)
Verify Sitecore Version
- Sitecore XP/XM 9.x - 10.x
- Sitecore JSS 21.x+ (for headless)
Backend Access
- Content Editor access
- Development environment
- Deploy permissions
Method 1: Layout File Integration (MVC)
Best for: Quick setup, standard Sitecore MVC sites
Basic Implementation
@* /Views/Shared/_Layout.cshtml *@
<!DOCTYPE html>
<html lang="@Sitecore.Context.Language.Name">
<head>
<meta charset="utf-8" />
<title>@Html.Sitecore().Field("Title", new { DisableWebEdit = true })</title>
@if (!Sitecore.Context.PageMode.IsExperienceEditorEditing)
{
<!-- Meta Pixel Code -->
<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('track', 'PageView');
</script>
<noscript>
<img height="1" width="1" style="display:none"
src="https://www.facebook.com/tr?id=YOUR_PIXEL_ID&ev=PageView&noscript=1"/>
</noscript>
<!-- End Meta Pixel Code -->
}
@Html.Sitecore().Placeholder("head")
</head>
<body>
@Html.Sitecore().Placeholder("main")
@RenderBody()
</body>
</html>
Multi-Site Configuration
1. Configure site properties:
<!-- App_Config/Include/Sites/Sites.config -->
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<sites>
<site name="website1"
hostName="www.site1.com"
database="web"
metaPixelId="1234567890123456" />
<site name="website2"
hostName="www.site2.com"
database="web"
metaPixelId="6543210987654321" />
</sites>
</sitecore>
</configuration>
2. Access in Layout:
@{
var pixelId = Sitecore.Context.Site.Properties["metaPixelId"];
}
@if (!string.IsNullOrEmpty(pixelId) && !Sitecore.Context.PageMode.IsExperienceEditorEditing)
{
<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', '@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"/>
</noscript>
}
Method 2: View Rendering Component
Best for: Reusable component, Content Editor management
Step 1: Create Data Template
/sitecore/templates/Feature/Analytics/Meta Pixel Settings
├── Fields
│ ├── Pixel ID (Single-Line Text)
│ ├── Enable Tracking (Checkbox)
│ ├── Enable Advanced Matching (Checkbox)
│ └── Test Event Code (Single-Line Text)
Step 2: Create Settings Item
Content Editor:
- Navigate to
/sitecore/content/[Your Site]/Settings - Insert new item from Meta Pixel Settings template
- Fill in Pixel ID
- Check Enable Tracking
Step 3: Create View
@* /Views/Analytics/MetaPixel.cshtml *@
@using Sitecore.Data.Items
@{
var settingsPath = $"/sitecore/content/{Sitecore.Context.Site.Name}/Settings/Meta Pixel Settings";
var settingsItem = Sitecore.Context.Database.GetItem(settingsPath);
if (settingsItem != null && !Sitecore.Context.PageMode.IsExperienceEditorEditing)
{
var pixelId = settingsItem["Pixel ID"];
var enableTracking = settingsItem["Enable Tracking"] == "1";
var enableAdvancedMatching = settingsItem["Enable Advanced Matching"] == "1";
var testEventCode = settingsItem["Test Event Code"];
if (enableTracking && !string.IsNullOrEmpty(pixelId))
{
<!-- Meta Pixel Code -->
<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');
@if (enableAdvancedMatching)
{
@* Advanced matching - requires user data *@
var userData = @Html.Raw(GetAdvancedMatchingData());
<text>fbq('init', '@pixelId', userData);</text>
}
else
{
<text>fbq('init', '@pixelId');</text>
}
fbq('track', 'PageView');
@if (!string.IsNullOrEmpty(testEventCode))
{
<text>fbq('track', 'PageView', {}, {'eventID': '@testEventCode'});</text>
}
</script>
<noscript>
<img height="1" width="1" style="display:none"
src="https://www.facebook.com/tr?id=@pixelId&ev=PageView&noscript=1"/>
</noscript>
<!-- End Meta Pixel Code -->
}
}
}
@functions {
string GetAdvancedMatchingData()
{
var userData = new System.Collections.Generic.Dictionary<string, string>();
// Only include if user is authenticated and has consented
if (Sitecore.Context.User?.IsAuthenticated == true)
{
var profile = Sitecore.Context.User.Profile;
if (!string.IsNullOrEmpty(profile.Email))
{
userData["em"] = HashEmail(profile.Email);
}
// Add other hashed user data as needed
}
return Newtonsoft.Json.JsonConvert.SerializeObject(userData);
}
string HashEmail(string email)
{
using (var sha256 = System.Security.Cryptography.SHA256.Create())
{
var bytes = System.Text.Encoding.UTF8.GetBytes(email.ToLower().Trim());
var hash = sha256.ComputeHash(bytes);
return BitConverter.ToString(hash).Replace("-", "").ToLower();
}
}
}
Method 3: Controller Rendering with Model
Best for: Complex logic, integration with Sitecore data
Create Model
// /Models/Analytics/MetaPixelModel.cs
using System.Collections.Generic;
namespace YourProject.Models.Analytics
{
public class MetaPixelModel
{
public string PixelId { get; set; }
public bool Enabled { get; set; }
public bool EnableAdvancedMatching { get; set; }
public string TestEventCode { get; set; }
public Dictionary<string, string> UserData { get; set; }
public bool IsExperienceEditor { get; set; }
public bool ShouldRender =>
Enabled &&
!string.IsNullOrEmpty(PixelId) &&
!IsExperienceEditor;
}
}
Create Controller
// /Controllers/AnalyticsController.cs
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using System.Web.Mvc;
using YourProject.Models.Analytics;
namespace YourProject.Controllers
{
public class AnalyticsController : Controller
{
public ActionResult MetaPixel()
{
var model = new MetaPixelModel
{
IsExperienceEditor = Sitecore.Context.PageMode.IsExperienceEditorEditing,
UserData = new Dictionary<string, string>()
};
var settingsPath = $"/sitecore/content/{Sitecore.Context.Site.Name}/Settings/Meta Pixel Settings";
var settingsItem = Sitecore.Context.Database.GetItem(settingsPath);
if (settingsItem != null)
{
model.PixelId = settingsItem["Pixel ID"];
model.Enabled = settingsItem["Enable Tracking"] == "1";
model.EnableAdvancedMatching = settingsItem["Enable Advanced Matching"] == "1";
model.TestEventCode = settingsItem["Test Event Code"];
if (model.EnableAdvancedMatching && Sitecore.Context.User?.IsAuthenticated == true)
{
var profile = Sitecore.Context.User.Profile;
if (!string.IsNullOrEmpty(profile.Email))
{
model.UserData["em"] = HashString(profile.Email.ToLower().Trim());
}
if (!string.IsNullOrEmpty(profile.GetCustomProperty("Phone")))
{
var phone = profile.GetCustomProperty("Phone");
model.UserData["ph"] = HashString(phone);
}
}
}
return View("/Views/Analytics/MetaPixel.cshtml", model);
}
private string HashString(string input)
{
using (SHA256 sha256 = SHA256.Create())
{
byte[] bytes = Encoding.UTF8.GetBytes(input);
byte[] hash = sha256.ComputeHash(bytes);
return System.BitConverter.ToString(hash).Replace("-", "").ToLower();
}
}
}
}
Create View
@* /Views/Analytics/MetaPixel.cshtml *@
@model YourProject.Models.Analytics.MetaPixelModel
@if (Model.ShouldRender)
{
<!-- Meta Pixel Code -->
<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');
@if (Model.EnableAdvancedMatching && Model.UserData.Count > 0)
{
var userData = @Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model.UserData));
<text>fbq('init', '@Model.PixelId', userData);</text>
}
else
{
<text>fbq('init', '@Model.PixelId');</text>
}
fbq('track', 'PageView');
</script>
<noscript>
<img height="1" width="1" style="display:none"
src="https://www.facebook.com/tr?id=@Model.PixelId&ev=PageView&noscript=1"/>
</noscript>
<!-- End Meta Pixel Code -->
}
Method 4: GTM Integration
Best for: Sites already using Google Tag Manager
Configure Meta Pixel via GTM
1. Create Custom HTML Tag in GTM:
Tag Type: Custom HTML Tag Configuration:
<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', '{{Meta Pixel ID}}');
fbq('track', 'PageView');
</script>
<noscript>
<img height="1" width="1" style="display:none"
src="https://www.facebook.com/tr?id={{Meta Pixel ID}}&ev=PageView&noscript=1"/>
</noscript>
Trigger: All Pages
2. Create Variable for Pixel ID:
Variable Name: Meta Pixel ID Variable Type: Constant Value: YOUR_PIXEL_ID
Method 5: Headless/JSS Implementation
Best for: Sitecore JSS (React, Vue, Next.js)
Next.js Implementation
// /src/components/Analytics/MetaPixel.tsx
import Script from 'next/script';
import { useSitecoreContext } from '@sitecore-jss/sitecore-jss-nextjs';
interface MetaPixelProps {
pixelId: string;
}
const MetaPixel = ({ pixelId }: MetaPixelProps): JSX.Element | null => {
const { sitecoreContext } = useSitecoreContext();
// Don't render in Experience Editor
if (sitecoreContext?.pageEditing || !pixelId) {
return null;
}
return (
<>
<Script
id="meta-pixel"
strategy="afterInteractive"
dangerouslySetInnerHTML={{
__html: `
!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');
`,
}}
/>
<noscript>
<img
height="1"
width="1"
style={{ display: 'none' }}
src={`https://www.facebook.com/tr?id=${pixelId}&ev=PageView&noscript=1`}
/>
</noscript>
</>
);
};
export default MetaPixel;
Add to Layout:
// /src/Layout.tsx
import MetaPixel from './components/Analytics/MetaPixel';
const Layout = ({ layoutData }: LayoutProps): JSX.Element => {
const PIXEL_ID = process.env.NEXT_PUBLIC_META_PIXEL_ID || '';
return (
<>
<MetaPixel pixelId={PIXEL_ID} />
<div>
{/* Your layout content */}
</div>
</>
);
};
React JSS Implementation
// /src/components/Analytics/MetaPixel.js
import { useEffect } from 'react';
import { useSitecoreContext } from '@sitecore-jss/sitecore-jss-react';
const MetaPixel = ({ fields }) => {
const { sitecoreContext } = useSitecoreContext();
const pixelId = fields?.pixelId?.value || process.env.REACT_APP_META_PIXEL_ID;
useEffect(() => {
if (sitecoreContext.pageEditing || !pixelId) {
return;
}
// Initialize 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, sitecoreContext.pageEditing]);
return null;
};
export default MetaPixel;
Advanced Matching
Enable advanced matching for better conversion tracking:
@{
var userData = new System.Collections.Generic.Dictionary<string, object>();
if (Sitecore.Context.User?.IsAuthenticated == true)
{
var profile = Sitecore.Context.User.Profile;
// Hash personal data before sending
if (!string.IsNullOrEmpty(profile.Email))
{
userData["em"] = HashEmail(profile.Email);
}
// Add other hashed user parameters
// fn (first name), ln (last name), ph (phone), ct (city), st (state), zp (zip)
}
var userDataJson = Newtonsoft.Json.JsonConvert.SerializeObject(userData);
}
<script>
fbq('init', 'YOUR_PIXEL_ID', @Html.Raw(userDataJson));
fbq('track', 'PageView');
</script>
Cookie Consent Integration
Implement consent before loading Meta Pixel:
<script>
function loadMetaPixel() {
if (localStorage.getItem('cookieConsent') === 'true') {
!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('track', 'PageView');
}
}
// Load if consent already given
if (localStorage.getItem('cookieConsent') === 'true') {
loadMetaPixel();
}
// Listen for consent event
document.addEventListener('cookieConsentGranted', loadMetaPixel);
</script>
Environment Configuration
Use web.config transformations for different environments:
Web.Release.config:
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<appSettings>
<add key="MetaPixel.Id"
value="PRODUCTION_PIXEL_ID"
xdt:Transform="SetAttributes"
xdt:Locator="Match(key)"/>
</appSettings>
</configuration>
Web.Debug.config:
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<appSettings>
<add key="MetaPixel.Id"
value="TEST_PIXEL_ID"
xdt:Transform="SetAttributes"
xdt:Locator="Match(key)"/>
</appSettings>
</configuration>
Validation and Testing
1. Meta Pixel Helper
Install Meta Pixel Helper Chrome extension:
- Visit your Sitecore site
- Click extension icon
- Verify pixel fires and shows green checkmark
2. Events Manager
Check Facebook Events Manager:
- Go to Events Manager > Test Events
- Enter Test Event Code
- Visit your site
- Verify events appear in Test Events tab
3. Browser DevTools
// Check if fbq is defined (browser console)
console.log(typeof fbq); // Should be "function"
// Check pixel initialization
console.log(window._fbq);
Common Issues
Issue: Pixel Not Loading in Experience Editor
Solution: Add Experience Editor check:
@if (!Sitecore.Context.PageMode.IsExperienceEditorEditing)
{
@* Pixel code *@
}
Issue: Duplicate Events
Cause: Pixel loaded multiple times
Solution: Ensure pixel code appears only once, preferably in main layout
Issue: Advanced Matching Not Working
Cause: Unhashed personal data or incorrect format
Solution: Always hash email and phone using SHA256