Meta Pixel Setup on Ghost | OpsBlu Docs

Meta Pixel Setup on Ghost

Install and configure Meta Pixel (Facebook Pixel) on Ghost websites for advertising and conversion tracking

Meta Pixel (formerly Facebook Pixel) enables Facebook and Instagram ad tracking, audience building, and conversion optimization for Ghost websites. This guide covers installation methods and Ghost-specific configuration.

Prerequisites

Before installing Meta Pixel on Ghost:

  • Meta Business Suite Account - Create at business.facebook.com
  • Meta Pixel Created - Set up pixel in Events Manager
  • Pixel ID - Obtain your pixel ID (format: 15-16 digit number)
  • Ghost Admin Access - Owner or Administrator role required
  • Domain Verified - Verify domain in Meta Business Suite (recommended)

Create Meta Pixel

If you haven't created a pixel yet:

  1. Navigate to Meta Events Manager
  2. Click Connect Data Sources → Web
  3. Select Meta Pixel
  4. Enter your Pixel Name (e.g., "Ghost Blog - Main Site")
  5. Optional: Enter your Ghost website URL
  6. Click Continue
  7. Copy your Pixel ID (you'll need this for installation)

Installation Methods

The easiest way to add Meta Pixel to Ghost without modifying theme files.

Step 1: Access Code Injection

  1. Log in to Ghost Admin (yourdomain.com/ghost)
  2. Navigate to Settings → Code Injection
  3. Locate the Site Header section

Step 2: Add Meta Pixel Base Code

Paste the following in Site Header:

<!-- 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_ID with your actual Meta Pixel ID.

Step 3: Save and Verify

  1. Click Save in the top-right corner
  2. Open your Ghost site in a new browser
  3. Install Meta Pixel Helper Chrome extension
  4. Verify pixel fires on page load

Method 2: Custom Theme Integration

For maximum control and access to Ghost Handlebars data.

Step 1: Download Your Theme

For Ghost(Pro):

  1. Navigate to Settings → Design
  2. Scroll to Installed Themes
  3. Click Download next to your active theme

For Self-Hosted:

cd /var/www/ghost/content/themes/
cp -r your-theme-name your-theme-name-meta

Step 2: Create Meta Pixel Partial

Create partials/meta-pixel.hbs:

{{!-- partials/meta-pixel.hbs --}}
<!-- 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');

// Track PageView with Ghost context
fbq('track', 'PageView', {
  {{#post}}
  content_type: 'post',
  content_name: '{{title}}',
  content_category: '{{primary_tag.name}}',
  content_ids: ['{{id}}'],
  {{/post}}
  {{#page}}
  content_type: 'page',
  content_name: '{{title}}',
  {{/page}}
  {{#is "home"}}
  content_type: 'homepage',
  {{/is}}
});
</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 -->

Step 3: Include Partial in default.hbs

Edit default.hbs and add before \{\{ghost_head\}\}:

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>{{meta_title}}</title>

    {{!-- Meta Pixel --}}
    {{> meta-pixel}}

    {{ghost_head}}
</head>

Step 4: Upload and Activate Theme

For Ghost(Pro):

  1. Zip your modified theme directory
  2. Navigate to Settings → Design → Change theme
  3. Upload ZIP file
  4. Click Activate

For Self-Hosted:

ghost restart

Then activate via Settings → Design.

Method 3: Google Tag Manager

If you're using GTM, deploy Meta Pixel through Tag Manager.

Step 1: Create Meta Pixel Tag

In GTM:

  1. Navigate to Tags → New
  2. Click Tag Configuration
  3. Select Custom HTML
  4. Paste Meta Pixel base code:
<!-- Meta Pixel via GTM -->
<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>
  1. Click Triggering → All Pages
  2. Name tag: "Meta Pixel - Base Code"
  3. Click Save

Step 2: Publish Container

  1. Click Submit
  2. Enter version name: "Add Meta Pixel"
  3. Click Publish

Enhanced Meta Pixel Configuration

Track Content Type

Differentiate between posts, pages, and homepage:

<script>
fbq('track', 'PageView', {
  content_type: '{{#is "post"}}post{{/is}}{{#is "page"}}page{{/is}}{{#is "home"}}homepage{{/is}}{{#is "tag"}}tag_archive{{/is}}{{#is "author"}}author_archive{{/is}}'
});
</script>

Track Member Status

Segment visitors by member status:

<script>
fbq('track', 'PageView', {
  {{#member}}
  user_type: 'member',
  member_status: '{{#if paid}}paid{{else}}free{{/if}}',
  {{/member}}
  {{^member}}
  user_type: 'visitor',
  {{/member}}
});
</script>

Track Post Metadata

Send article details to Meta:

{{#post}}
<script>
fbq('track', 'ViewContent', {
  content_name: '{{title}}',
  content_category: '{{primary_tag.name}}',
  content_type: 'article',
  content_ids: ['{{id}}'],
  {{#if primary_author}}
  author: '{{primary_author.name}}',
  {{/if}}
  published_date: '{{published_at}}',
  {{#if featured}}
  featured: true,
  {{/if}}
  visibility: '{{visibility}}'
});
</script>
{{/post}}

Advanced Event Tracking

Meta Pixel supports standard events for conversion tracking:

Member Signup Event

<script>
window.addEventListener('portal-signup', function() {
  if (typeof fbq !== 'undefined') {
    fbq('track', 'Lead', {
      content_name: 'Member Signup',
      content_category: 'Membership',
      {{#member}}
      status: '{{#if paid}}paid{{else}}free{{/if}}'
      {{/member}}
    });
  }
});
</script>

Newsletter Subscription

<script>
window.addEventListener('portal-subscribe', function() {
  if (typeof fbq !== 'undefined') {
    fbq('track', 'Subscribe', {
      content_name: 'Newsletter Subscription',
      predicted_ltv: 0,
      value: 0,
      currency: 'USD'
    });
  }
});
</script>
<script>
{{#if @member.subscriptions}}
// Track subscription as purchase
if (typeof fbq !== 'undefined') {
  fbq('track', 'Purchase', {
    content_name: '{{@member.subscriptions.[0].tier.name}}',
    content_type: 'subscription',
    content_ids: ['{{@member.subscriptions.[0].tier.id}}'],
    currency: '{{@member.subscriptions.[0].tier.currency}}',
    value: {{@member.subscriptions.[0].tier.monthly_price}},
    predicted_ltv: {{multiply @member.subscriptions.[0].tier.monthly_price 12}}
  });
}
{{/if}}
</script>

Conversion API (Server-Side Tracking)

For enhanced privacy and iOS 14+ tracking, implement Meta Conversion API.

Step 1: Generate Access Token

  1. Navigate to Meta Events Manager
  2. Select your pixel
  3. Click Settings
  4. Scroll to Conversions API
  5. Click Generate Access Token
  6. Copy the token (keep it secure)

Step 2: Server-Side Implementation

Create a Node.js webhook handler:

// conversion-api-handler.js
const crypto = require('crypto');
const axios = require('axios');

async function sendToConversionAPI(event, userData) {
  const accessToken = process.env.META_CAPI_ACCESS_TOKEN;
  const pixelId = process.env.META_PIXEL_ID;

  // Hash user data for privacy
  const hashedEmail = userData.email
    ? crypto.createHash('sha256').update(userData.email).digest('hex')
    : null;

  const payload = {
    data: [{
      event_name: event.name,
      event_time: Math.floor(Date.now() / 1000),
      action_source: 'website',
      event_source_url: event.url,
      user_data: {
        em: hashedEmail,
        client_ip_address: event.ip,
        client_user_agent: event.userAgent,
        fbc: event.fbc, // Facebook click ID
        fbp: event.fbp  // Facebook browser ID
      },
      custom_data: event.customData
    }]
  };

  try {
    const response = await axios.post(
      `https://graph.facebook.com/v18.0/${pixelId}/events`,
      payload,
      {
        params: { access_token: accessToken }
      }
    );
    console.log('CAPI Response:', response.data);
  } catch (error) {
    console.error('CAPI Error:', error.response?.data);
  }
}

// Example: Track member signup
sendToConversionAPI(
  {
    name: 'Lead',
    url: 'https://yoursite.com',
    ip: '1.2.3.4',
    userAgent: 'Mozilla/5.0...',
    fbc: '_fbc_value',
    fbp: '_fbp_value',
    customData: {
      content_name: 'Member Signup',
      content_category: 'Membership'
    }
  },
  { email: 'user@example.com' }
);

Step 3: Integrate with Ghost Webhooks

Use Ghost webhooks to trigger server-side events:

  1. Navigate to Ghost Admin → Settings → Integrations
  2. Click Add custom integration
  3. Enter name: "Meta Conversion API"
  4. Click Create
  5. Copy Webhook URL
  6. Configure webhook to send member.added events to your server

Performance Optimization

Preconnect to Meta Domains

Add to theme <head>:

<link rel="preconnect" href="https://connect.facebook.net">
<link rel="dns-prefetch" href="//connect.facebook.net">

Async Loading

Meta Pixel loads asynchronously by default. For additional control:

// Delay Meta Pixel until after page load
window.addEventListener('load', function() {
  // Load Meta Pixel script here
});

Conditional Loading

Only load on specific content types:

{{!-- Only load Meta Pixel on posts and pages --}}
{{#is "post, page"}}
  {{> meta-pixel}}
{{/is}}

Domain Verification

Verify your Ghost domain in Meta Business Suite for iOS 14+ tracking:

  1. Navigate to Meta Business Suite → Settings → Brand Safety → Domains
  2. Click Add
  3. Enter your Ghost domain
  4. Select verification method:
    • HTML Tag - Add meta tag to Ghost code injection
    • DNS TXT Record - Add DNS record to domain

HTML Tag Method:

  1. Copy the meta tag from Meta Business Suite
  2. Paste in Ghost Settings → Code Injection → Site Header:
<meta name="facebook-domain-verification" content="your-verification-code" />
  1. Click Save
  2. Return to Meta Business Suite and click Verify

Testing and Validation

Meta Pixel Helper

  1. Install Meta Pixel Helper Chrome extension
  2. Navigate to your Ghost site
  3. Click extension icon
  4. Verify:
    • Pixel loads successfully (green checkmark)
    • PageView event fires
    • No errors or warnings

Test Events Tool

Use Meta's Test Events feature:

  1. Navigate to Events Manager → Test Events
  2. Copy your Test Event Code
  3. Add to Ghost code injection:
<script>
fbq('init', 'YOUR_PIXEL_ID', {}, {
  agent: 'test_event_code',
  test_event_code: 'TEST12345'
});
</script>
  1. Trigger events on your Ghost site
  2. Verify events appear in Test Events dashboard

Browser Console

Check for Meta Pixel in console:

// Verify fbq function exists
console.log(typeof fbq);
// Expected: "function"

// Check pixel version
console.log(fbq.version);
// Expected: "2.0"

// Manual event test
fbq('track', 'PageView');

Common Issues

Pixel Not Firing

  • Verify Pixel ID - Check for typos in pixel ID
  • Ad Blockers - Test in incognito without extensions
  • Code Placement - Ensure pixel in <head> before \{\{ghost_head\}\}
  • JavaScript Errors - Check browser console for errors

Multiple Pixel Fires

  • Code Injection + Theme - Remove duplicate implementations
  • GTM + Direct - Use only one method (GTM or direct)
  • Meta Pixel Helper - Shows "Multiple Pixels" warning

Events Not Recording

  • Pixel Not Active - Verify pixel is active in Events Manager
  • Domain Mismatch - Ensure domain matches pixel configuration
  • Ad Blockers - Users with ad blockers won't track
  • iOS 14+ Issues - Implement domain verification and CAPI

Performance Impact

  • Too Many Events - Limit custom events
  • Large Payloads - Keep custom data minimal
  • Synchronous Loading - Ensure async attribute present

Ghost(Pro) vs. Self-Hosted

Ghost(Pro)

  • Code Injection: Recommended (no theme upload needed)
  • Theme Method: Requires theme upload
  • CAPI: Requires external server for webhooks
  • Domain Verification: Fully supported

Self-Hosted

  • File Access: Direct theme editing
  • Server-Side CAPI: Can run on same server
  • Custom Events: Full control over event tracking
  • Webhooks: Can handle internally

Next Steps