Installing Meta Pixel on TYPO3 | OpsBlu Docs

Installing Meta Pixel on TYPO3

Complete guide to implementing Meta Pixel (Facebook Pixel) on TYPO3 using TypoScript, Fluid templates, and extensions

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:

  1. Create Meta Pixel in Facebook Business Manager

  2. Verify TYPO3 Version

    • TYPO3 11 LTS or newer recommended
    • PHP 7.4+ required
  3. 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

  1. Navigate to Extension Manager

    • Admin Tools → Extensions → Get Extensions
    • Search for "facebook pixel" or "meta pixel"
    • Click Import and Install
  2. 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>

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]
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:

  • TypoScript not included in active template
  • Backend user logged in (if excluded)
  • Cache not cleared

Solutions:

  1. Check Web → Template → Template Analyzer
  2. Log out of TYPO3 backend
  3. 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'

Next Steps