This guide covers TYPO3-specific methods for implementing Meta Pixel (Facebook Pixel), from extension-based installations to custom TypoScript and Fluid template integrations.
Prerequisites
Before installing Meta Pixel on TYPO3:
Create Meta Pixel in Facebook Business Manager
- Go to Facebook Events Manager
- Create a new Pixel
- Copy your Pixel ID (15-16 digit number)
Verify TYPO3 Version
- TYPO3 11 LTS or newer recommended
- PHP 7.4+ required
Backend Access
- Extension Manager access
- TypoScript template editing permissions
Method 1: Extension-Based Installation
Best for: Quick setup, non-technical users, standard tracking needs
Using facebook_pixel Extension
Search for Meta/Facebook Pixel extensions in TYPO3 Extension Repository (TER).
Installation via Extension Manager
Navigate to Extension Manager
- Admin Tools → Extensions → Get Extensions
- Search for "facebook pixel" or "meta pixel"
- Click Import and Install
Activate Extension
- Admin Tools → Extensions → Installed Extensions
- Find the extension and click Activate
Installation via Composer
composer require vendor/facebook-pixel
Then activate:
./vendor/bin/typo3 extension:activate facebook_pixel
Extension Configuration
Admin Tools → Settings → Extension Configuration → facebook_pixel
Pixel ID: 1234567890123456
Enable tracking: Yes
Exclude backend users: Yes
Cookie consent mode: Enabled
Method 2: TypoScript Implementation
Best for: Full control, custom implementations, multi-site setups
Basic TypoScript Setup
Add to your site template (Web → Template → Info/Modify → Setup):
# Meta Pixel Base Code
page.headerData.200 = TEXT
page.headerData.200.value (
<!-- 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', '1234567890123456');
fbq('track', 'PageView');
</script>
<noscript>
<img height="1" width="1" style="display:none"
src="https://www.facebook.com/tr?id=1234567890123456&ev=PageView&noscript=1"/>
</noscript>
<!-- End Meta Pixel Code -->
)
TypoScript with Constants
Constants (Web → Template → Info/Modify → Constants):
# Meta Pixel Configuration
metaPixel {
pixelId = 1234567890123456
enabled = 1
excludeBackendUsers = 1
}
Setup:
[{$metaPixel.enabled} == 1]
# Exclude backend users
[backend.user.isLoggedIn == false || {$metaPixel.excludeBackendUsers} == 0]
page.headerData.200 = TEXT
page.headerData.200.value (
<!-- 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', '{$metaPixel.pixelId}');
fbq('track', 'PageView');
</script>
<noscript>
<img height="1" width="1" style="display:none"
src="https://www.facebook.com/tr?id={$metaPixel.pixelId}&ev=PageView&noscript=1"/>
</noscript>
<!-- End Meta Pixel Code -->
)
[END]
[END]
Multi-Site Configuration
For different sites with different Pixels:
# Main site
[siteIdentifier = "main-site"]
page.headerData.200 = TEXT
page.headerData.200.value (
<script>
!function(f,b,e,v,n,t,s){...}(window, document,'script','https://connect.facebook.net/en_US/fbevents.js');
fbq('init', '1111111111111111');
fbq('track', 'PageView');
</script>
)
[END]
# Secondary site
[siteIdentifier = "secondary-site"]
page.headerData.200 = TEXT
page.headerData.200.value (
<script>
!function(f,b,e,v,n,t,s){...}(window, document,'script','https://connect.facebook.net/en_US/fbevents.js');
fbq('init', '2222222222222222');
fbq('track', 'PageView');
</script>
)
[END]
Site Configuration YAML
Store Pixel ID in site configuration (config/sites/main/config.yaml):
settings:
metaPixel:
pixelId: '1234567890123456'
enabled: true
Access in TypoScript:
page.headerData.200 = TEXT
page.headerData.200.value (
<script>
!function(f,b,e,v,n,t,s){...}(window, document,'script','https://connect.facebook.net/en_US/fbevents.js');
fbq('init', '{site:settings.metaPixel.pixelId}');
fbq('track', 'PageView');
</script>
)
Method 3: Fluid Template Integration
Best for: Developers, template-based control, conditional loading
Base Layout Template
Edit your main layout (typo3conf/ext/your_sitepackage/Resources/Private/Layouts/Page.html):
<!DOCTYPE html>
<html lang="{language}">
<head>
<meta charset="utf-8">
<title>{page.title}</title>
<!-- Meta Pixel Code -->
<f:if condition="{settings.metaPixel.enabled}">
<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', '{settings.metaPixel.pixelId}');
fbq('track', 'PageView');
</script>
<noscript>
<img height="1" width="1" style="display:none"
src="https://www.facebook.com/tr?id={settings.metaPixel.pixelId}&ev=PageView&noscript=1"/>
</noscript>
</f:if>
</head>
<body>
<f:render section="Main" />
</body>
</html>
TypoScript Settings for Fluid
page {
10 = FLUIDTEMPLATE
10 {
templateRootPaths {
0 = EXT:your_sitepackage/Resources/Private/Templates/
}
layoutRootPaths {
0 = EXT:your_sitepackage/Resources/Private/Layouts/
}
settings {
metaPixel {
enabled = 1
pixelId = 1234567890123456
}
}
}
}
Conditional Pixel Partial
Create Resources/Private/Partials/Analytics/MetaPixel.html:
<f:if condition="{settings.metaPixel.enabled}">
<f:comment><!-- Only load for non-backend users --></f:comment>
<f:if condition="{TSFE.beUserLogin} == 0">
<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');
<f:if condition="{settings.metaPixel.advancedMatching}">
<f:then>
// Advanced Matching
fbq('init', '{settings.metaPixel.pixelId}', {
em: '<f:if condition="{user.email}">{user.email -> f:format.sha256()}</f:if>',
ph: '<f:if condition="{user.phone}">{user.phone -> f:format.sha256()}</f:if>',
fn: '<f:if condition="{user.firstName}">{user.firstName -> f:format.sha256()}</f:if>',
ln: '<f:if condition="{user.lastName}">{user.lastName -> f:format.sha256()}</f:if>'
});
</f:then>
<f:else>
fbq('init', '{settings.metaPixel.pixelId}');
</f:else>
</f:if>
fbq('track', 'PageView');
</script>
<noscript>
<img height="1" width="1" style="display:none"
src="https://www.facebook.com/tr?id={settings.metaPixel.pixelId}&ev=PageView&noscript=1"/>
</noscript>
</f:if>
</f:if>
Include in your layout:
<f:render partial="Analytics/MetaPixel" arguments="{_all}" />
Method 4: Site Package Integration
Best for: Enterprise, version control, maintainable code
Site Package Structure
your_sitepackage/
├── Configuration/
│ ├── TypoScript/
│ │ ├── constants.typoscript
│ │ └── setup.typoscript
├── Resources/
│ ├── Private/
│ │ ├── Layouts/
│ │ ├── Partials/
│ │ │ └── Analytics/
│ │ │ └── MetaPixel.html
│ │ └── Templates/
│ └── Public/
│ └── JavaScript/
│ └── meta-pixel-events.js
└── ext_emconf.php
constants.typoscript
# cat=meta-pixel/enable/10; type=boolean; label=Enable Meta Pixel
metaPixel.enabled = 1
# cat=meta-pixel/basic/20; type=string; label=Meta Pixel ID
metaPixel.pixelId = 1234567890123456
# cat=meta-pixel/privacy/30; type=boolean; label=Exclude Backend Users
metaPixel.excludeBackendUsers = 1
# cat=meta-pixel/advanced/40; type=boolean; label=Enable Advanced Matching
metaPixel.advancedMatching = 0
# cat=meta-pixel/privacy/50; type=boolean; label=Require Cookie Consent
metaPixel.requireConsent = 0
setup.typoscript
[{$metaPixel.enabled} == 1]
[backend.user.isLoggedIn == false || {$metaPixel.excludeBackendUsers} == 0]
page {
headerData {
200 = TEXT
200.value (
<!-- 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', '{$metaPixel.pixelId}');
fbq('track', 'PageView');
</script>
<noscript>
<img height="1" width="1" style="display:none"
src="https://www.facebook.com/tr?id={$metaPixel.pixelId}&ev=PageView&noscript=1"/>
</noscript>
<!-- End Meta Pixel Code -->
)
}
# Include custom event tracking
includeJSFooter {
metaPixelEvents = EXT:your_sitepackage/Resources/Public/JavaScript/meta-pixel-events.js
}
}
[END]
[END]
Advanced Matching (GDPR-Compliant)
Advanced Matching helps improve attribution by matching logged-in users.
TypoScript with Advanced Matching
[frontend.user.isLoggedIn == true]
page.headerData.200 = TEXT
page.headerData.200.stdWrap.dataWrap (
<script>
!function(f,b,e,v,n,t,s){...}(window, document,'script','https://connect.facebook.net/en_US/fbevents.js');
// Advanced Matching (hashed)
fbq('init', '{$metaPixel.pixelId}', {
em: '{TSFE:fe_user|user|email -> f:format.sha256()}',
ph: '{TSFE:fe_user|user|telephone -> f:format.sha256()}',
fn: '{TSFE:fe_user|user|first_name -> f:format.sha256()}',
ln: '{TSFE:fe_user|user|last_name -> f:format.sha256()}'
});
fbq('track', 'PageView');
</script>
)
[END]
PHP-Based Hashing (More Secure)
Create a custom ViewHelper:
<?php
namespace Vendor\Extension\ViewHelpers;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
class Sha256ViewHelper extends AbstractViewHelper
{
public function initializeArguments()
{
$this->registerArgument('value', 'string', 'Value to hash', true);
}
public function render()
{
$value = $this->arguments['value'];
return $value ? hash('sha256', strtolower(trim($value))) : '';
}
}
Use in Fluid:
<f:if condition="{user.email}">
fbq('init', '{settings.metaPixel.pixelId}', {
em: '{user.email -> myext:sha256()}'
});
</f:if>
Cookie Consent Integration
With cookieman Extension
# Only load Meta Pixel after consent
[getTenv('HTTP_COOKIE') =~ '/cookieman=[^;]*trackingMetaPixel[^;]*/' ]
page.headerData.200 = TEXT
page.headerData.200.value (
<script>
!function(f,b,e,v,n,t,s){...}(window, document,'script','https://connect.facebook.net/en_US/fbevents.js');
fbq('init', '{$metaPixel.pixelId}');
fbq('track', 'PageView');
</script>
)
[END]
Manual Consent Mode
page.headerData.200 = TEXT
page.headerData.200.value (
<script>
// Load fbq but don't initialize until consent
!function(f,b,e,v,n,t,s){...}(window, document,'script','https://connect.facebook.net/en_US/fbevents.js');
// Wait for consent
document.addEventListener('cookieConsentGranted', function() {
fbq('init', '{$metaPixel.pixelId}');
fbq('track', 'PageView');
});
</script>
)
Performance Optimization
Preconnect to Facebook Domains
page {
headerData {
10 = TEXT
10.value (
<link rel="preconnect" href="https://connect.facebook.net">
<link rel="dns-prefetch" href="https://connect.facebook.net">
)
}
}
Delayed Loading
page.jsFooterInline.300 = TEXT
page.jsFooterInline.300.value (
// Delay Meta Pixel loading until user interaction
let fbqLoaded = false;
const loadMetaPixel = () => {
if (fbqLoaded) return;
fbqLoaded = true;
!function(f,b,e,v,n,t,s){...}(window, document,'script','https://connect.facebook.net/en_US/fbevents.js');
fbq('init', '{$metaPixel.pixelId}');
fbq('track', 'PageView');
};
['mousedown', 'touchstart', 'scroll'].forEach(event => {
window.addEventListener(event, loadMetaPixel, {once: true, passive: true});
});
setTimeout(loadMetaPixel, 3000); // Fallback after 3s
)
Validation and Testing
1. Meta Pixel Helper
Install Meta Pixel Helper Chrome extension:
- Visit your TYPO3 site
- Click the extension icon
- Verify Pixel ID appears
- Check for any errors or warnings
2. Facebook Events Manager
- Go to Events Manager → Test Events
- Enter your website URL
- Navigate your site
- Verify events appear in real-time
3. TYPO3 Debug
Clear TYPO3 caches:
./vendor/bin/typo3 cache:flush
Or in Backend: Admin Tools → Maintenance → Flush Caches
4. Browser Developer Tools
// Check if fbq is loaded (browser console)
console.log(typeof fbq);
console.log(window._fbq);
// Manually fire test event
fbq('track', 'TestEvent', {test: true});
Common TYPO3-Specific Issues
Issue: Pixel Not Loading
Causes:
Solutions:
- Check Web → Template → Template Analyzer
- Log out of TYPO3 backend
- Flush all caches
Issue: Duplicate Events
Cause: Pixel code loaded multiple times
Solution:
# Ensure only one pixel code block exists
page.headerData.200 >
page.headerData.200 = TEXT
page.headerData.200.value (...)
Issue: Multi-Site Conflicts
Solution: Use site-specific configuration:
# config/sites/main/config.yaml
settings:
metaPixel:
pixelId: '1234567890123456'