Learn how to install Meta Pixel (formerly Facebook Pixel) on your Concrete CMS website using Header/Footer blocks, page template integration, or Google Tag Manager.
Installation Methods
| Method | Difficulty | Customization | Events | Recommended |
|---|---|---|---|---|
| Header/Footer Block | Easy | Low | Basic | Quick setup |
| Page Template | Medium | High | Full control | Custom implementations |
| Google Tag Manager | Medium | Highest | Advanced | Best practice |
Method 1: Header/Footer Block (Easiest)
Use Concrete CMS's built-in tracking code functionality to add Meta Pixel site-wide.
Step 1: Get Your Pixel ID
- Go to Meta Events Manager
- Select your Pixel
- Copy your Pixel ID (16-digit number)
Step 2: Add via Dashboard
Concrete CMS v9+:
Access Tracking Codes
- Log in to Dashboard
- Go to System & Settings → SEO & Statistics → Tracking Codes
Add Meta Pixel Code
In the "Tracking Code (Header)" field, add:
<!-- 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 -->Replace
YOUR_PIXEL_IDwith your actual Pixel ID.Save Settings
- Click Save
Clear Cache
- Dashboard → System & Settings → Optimization → Clear Cache
What Gets Tracked (Header/Footer Method)
Automatic Events:
PageView- All page views- Basic user navigation
Requires Additional Setup:
ViewContent- Product/content viewsAddToCart- Cart additionsLead- Form submissionsPurchase- Order completions
Method 2: Page Template Installation
Add Meta Pixel directly to your theme templates for more control.
Step 1: Locate Theme Files
Your theme files are typically in:
/application/themes/[your-theme-name]/
Or for package themes:
/packages/[package-name]/themes/[theme-name]/
Step 2: Add Base Pixel Code
Open your theme's main layout file (often view.php or default.php).
Find the </head> closing tag and add above it:
<?php
// Exclude Meta Pixel from edit mode and dashboard
if (!$c->isEditMode() && !$this->controller->isControllerTaskInstanceOf('DashboardPageController')) {
?>
<!-- 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 -->
<?php
}
?>
</head>
Replace YOUR_PIXEL_ID with your actual Pixel ID.
Step 3: Add Advanced Matching (Recommended)
For better attribution, send hashed user data:
<?php
if (!$c->isEditMode() && !$this->controller->isControllerTaskInstanceOf('DashboardPageController')) {
$app = \Concrete\Core\Support\Facade\Application::getFacadeApplication();
$u = $app->make(\Concrete\Core\User\User::class);
?>
<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');
<?php
if ($u->isRegistered()) {
$userInfo = $u->getUserInfoObject();
$email = strtolower($userInfo->getUserEmail());
$firstName = strtolower($userInfo->getUserObject()->getUserFirstName());
$lastName = strtolower($userInfo->getUserObject()->getUserLastName());
?>
fbq('init', 'YOUR_PIXEL_ID', {
em: '<?php echo $email; ?>',
fn: '<?php echo $firstName; ?>',
ln: '<?php echo $lastName; ?>'
});
<?php
} else {
?>
fbq('init', 'YOUR_PIXEL_ID');
<?php
}
?>
fbq('track', 'PageView');
</script>
<?php
}
?>
Note: Meta automatically hashes this data client-side.
Step 4: Add ViewContent Event
For blog posts or content pages:
<?php
if (!$c->isEditMode() && $c->getPageTypeHandle() === 'blog_entry') {
$pageName = $c->getCollectionName();
$pageID = $c->getCollectionID();
?>
<script>
fbq('track', 'ViewContent', {
content_name: '<?php echo addslashes($pageName); ?>',
content_category: 'Blog Post',
content_ids: ['<?php echo $pageID; ?>'],
content_type: 'product'
});
</script>
<?php
}
?>
Step 5: Add Lead Event (Form Submissions)
Add to form block template or success page:
<?php
// On form submission success page or thank you page
if (!$c->isEditMode() && $c->getCollectionPath() === '/thank-you') {
?>
<script>
fbq('track', 'Lead', {
content_name: 'Contact Form',
content_category: 'Form Submission'
});
</script>
<?php
}
?>
Step 6: Track Form Submissions via JavaScript
For real-time form tracking:
<script>
document.addEventListener('DOMContentLoaded', function() {
const forms = document.querySelectorAll('form[action*="/ccm/system/form/submit"]');
forms.forEach(function(form) {
form.addEventListener('submit', function(e) {
const formName = form.getAttribute('data-form-name') || 'Unknown Form';
fbq('track', 'Lead', {
content_name: formName,
content_category: 'Form'
});
});
});
});
</script>
Method 3: Google Tag Manager (Recommended)
Using GTM provides easier management and better integration.
Prerequisites
- GTM installed on Concrete CMS
- Meta Pixel ID
Setup Steps
Create Meta Pixel Tag in GTM
a. In GTM, go to Tags → New
b. Tag Configuration → Custom HTML
c. Add Meta Pixel base 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>d. Triggering: All Pages
e. Name:
Meta Pixel - Base Codef. Save
Create ViewContent Event Tag
a. Tags → New
b. Tag Configuration → Custom HTML
<script> fbq('track', 'ViewContent', { content_name: {{Page Name}}, content_category: {{Page Type}}, content_ids: [{{Page ID}}], content_type: 'product' }); </script>c. Triggering: Create trigger for blog posts or specific page types
d. Name:
Meta Pixel - ViewContentCreate Lead Event Tag (Form Submissions)
a. Tags → New
b. Tag Configuration → Custom HTML
<script> fbq('track', 'Lead', { content_name: {{Form Name}}, content_category: 'Form Submission' }); </script>c. Triggering: Form Submission trigger
d. Name:
Meta Pixel - LeadPublish Container
- Click Submit
- Name version
- Publish
E-Commerce Tracking (Community Store)
If using Community Store add-on:
Product View Event
Add to product page template:
<?php
if (isset($product) && !$c->isEditMode()) {
?>
<script>
fbq('track', 'ViewContent', {
content_name: '<?php echo addslashes($product->getName()); ?>',
content_category: '<?php echo addslashes($product->getGroupName()); ?>',
content_ids: ['<?php echo $product->getID(); ?>'],
content_type: 'product',
value: <?php echo $product->getPrice(); ?>,
currency: '<?php echo \Config::get('community_store.currency'); ?>'
});
</script>
<?php
}
?>
Add to Cart Event
<script>
document.addEventListener('DOMContentLoaded', function() {
document.querySelectorAll('form.store-form-add-to-cart').forEach(function(form) {
form.addEventListener('submit', function(e) {
const productId = form.querySelector('input[name="pID"]')?.value;
const productName = form.querySelector('.product-name')?.textContent;
const productPrice = form.querySelector('.product-price')?.getAttribute('data-price');
fbq('track', 'AddToCart', {
content_name: productName,
content_ids: [productId],
content_type: 'product',
value: parseFloat(productPrice),
currency: 'USD'
});
});
});
});
</script>
Purchase Event
Add to order confirmation page:
<?php
if (isset($order) && !$c->isEditMode()) {
$items = [];
foreach ($order->getOrderItems() as $item) {
$items[] = $item->getProductID();
}
?>
<script>
fbq('track', 'Purchase', {
content_ids: <?php echo json_encode($items); ?>,
content_type: 'product',
value: <?php echo $order->getTotal(); ?>,
currency: '<?php echo \Config::get('community_store.currency'); ?>',
num_items: <?php echo count($items); ?>
});
</script>
<?php
}
?>
Verification & Testing
1. Meta Pixel Helper
Install Meta Pixel Helper Chrome extension:
- Green icon = Pixel working correctly
- Yellow = Warnings
- Red = Errors
2. Meta Events Manager
Check real-time events:
- Go to Events Manager
- Select your Pixel
- Click Test Events
- Enter your website URL
- Navigate your site and watch events appear
3. Test Full Funnel
- View content → Check
ViewContent - Submit form → Check
Lead - Add to cart (if e-commerce) → Check
AddToCart - Complete purchase (if e-commerce) → Check
Purchase
4. Verify Event Parameters
Ensure events include:
content_ids(page/product IDs)content_name(page/product names)value(numeric, no currency symbols)currency(ISO code: USD, EUR, etc.)
Troubleshooting
Pixel Not Loading
Check:
- Pixel ID is correct (16 digits)
- No JavaScript errors in console
- Ad blockers disabled for testing
- Concrete CMS cache cleared
- Not in edit mode
Events Fire in Edit Mode
Problem: Pixel tracking when editing pages.
Solution: Always add edit mode check:
<?php if (!$c->isEditMode()) { ?>
// Meta Pixel code
<?php } ?>
Duplicate Events
Cause: Multiple implementations (Header block + Template code).
Fix:
- Check Dashboard tracking codes
- Check theme template files
- Remove duplicate implementations
- Use GTM to consolidate
Form Events Not Firing
Problem: Lead event doesn't fire on form submission.
Solution: Add event listener with delay:
form.addEventListener('submit', function(e) {
e.preventDefault();
fbq('track', 'Lead', {
content_name: formName
});
// Submit after short delay
setTimeout(function() {
form.submit();
}, 300);
});
Cache Issues
Problem: Pixel changes don't appear.
Solution: Clear Concrete CMS cache:
- Dashboard → System & Settings → Optimization → Clear Cache
Privacy & Compliance
Cookie Consent Integration
Wait for user consent before loading Meta Pixel:
<script>
// Check for consent cookie
if (document.cookie.indexOf('marketing_consent=true') !== -1) {
// Load Meta Pixel
!function(f,b,e,v,n,t,s) {
// Pixel code here
}(window, document,'script','https://connect.facebook.net/en_US/fbevents.js');
fbq('init', 'YOUR_PIXEL_ID');
fbq('track', 'PageView');
}
</script>
Limited Data Use (California)
For CCPA compliance:
fbq('dataProcessingOptions', ['LDU'], 1, 1000);
GDPR Compliance
Configure data processing options in Meta Events Manager:
- Events Manager → Settings → Data Processing Options
Conversions API (Server-Side Tracking)
For improved tracking accuracy (especially for iOS 14+):
Using Concrete CMS Form Events
Create custom code to send server-side events when forms are submitted:
<?php
// In your form submission handler
use Concrete\Core\Http\Client\Client as HttpClient;
$client = new HttpClient();
$pixelId = 'YOUR_PIXEL_ID';
$accessToken = 'YOUR_ACCESS_TOKEN';
$data = [
'data' => [[
'event_name' => 'Lead',
'event_time' => time(),
'user_data' => [
'em' => hash('sha256', strtolower($email)),
'ph' => hash('sha256', preg_replace('/[^0-9]/', '', $phone))
],
'event_source_url' => \Core::make('url/canonical')->resolve([$c]),
'action_source' => 'website'
]],
'access_token' => $accessToken
];
$response = $client->post(
"https://graph.facebook.com/v18.0/{$pixelId}/events",
['json' => $data]
);
Note: Requires Meta Conversions API access token.
Next Steps
- GA4 Setup - Install Google Analytics 4
- GTM Setup - Install GTM for easier management
- Events Not Firing - Debug tracking issues
For general Meta Pixel concepts, see Meta Pixel Guide.