Google Tag Manager Setup on Ghost | OpsBlu Docs

Google Tag Manager Setup on Ghost

Install and configure Google Tag Manager on Ghost websites using code injection or custom themes

Google Tag Manager (GTM) provides centralized control over all marketing and analytics tags without modifying Ghost theme files. This guide covers GTM installation on Ghost(Pro) and self-hosted Ghost installations.

Why Use GTM with Ghost

Benefits for Ghost Sites

  • No Theme Edits - Add/modify tags via GTM interface, not Ghost theme
  • Team Collaboration - Marketing teams can manage tags without developer involvement
  • Version Control - Built-in versioning and rollback capabilities
  • Multi-Tool Management - Single container for GA4, Meta Pixel, LinkedIn, etc.
  • Conditional Loading - Load tags based on Ghost content type, member status, etc.
  • Performance Control - Async tag loading and priority management

GTM vs. Direct Code Injection

Feature GTM Direct Code Injection
Setup Complexity Medium Low
Tag Changes No code changes needed Requires admin access
Performance Additional container overhead Minimal overhead
Debugging Tools Built-in Tag Assistant Browser console only
Team Management Multi-user with permissions Single admin login
Analytics GA4, Meta, LinkedIn, etc. One tool at a time

Prerequisites

Before installing GTM on Ghost:

  • GTM Account - Create account at tagmanager.google.com
  • GTM Container - Set up a web container for your Ghost site
  • Ghost Admin Access - Owner or Administrator role
  • Container ID - Format: GTM-XXXXXXX

GTM Container Setup

Step 1: Create GTM Container

  1. Navigate to Google Tag Manager
  2. Click Create Account or use existing account
  3. Enter Account Name (your company/site name)
  4. Click Add Container
  5. Enter Container Name (your Ghost domain)
  6. Select Target Platform: Web
  7. Click Create
  8. Accept the Terms of Service
  9. Copy the provided container code snippets

Step 2: Obtain Container Code

After creating the container, GTM provides two code snippets:

Head Snippet:

<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXXX');</script>
<!-- End Google Tag Manager -->

Body Snippet:

<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->

Ghost's built-in code injection is the fastest way to add GTM without theme modifications.

Step 1: Access Ghost Code Injection

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

Step 2: Add GTM Head Snippet

Paste the GTM head snippet in the Site Header field:

<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXXX');</script>
<!-- End Google Tag Manager -->

Step 3: Add GTM Body Snippet

Paste the GTM noscript snippet in the Site Footer field (it loads at the top of <body> in Ghost):

<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->

Step 4: Save and Verify

  1. Click Save in the top-right corner
  2. Open your Ghost site in a new browser tab
  3. Open browser DevTools → Console
  4. Verify dataLayer exists: type dataLayer in console
  5. Install Google Tag Assistant extension and verify GTM container loads

Method 2: Custom Theme Integration

For advanced control and Ghost-specific data layer variables, integrate GTM into your theme.

Step 1: Download 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-gtm

Step 2: Add GTM to default.hbs

Edit default.hbs and add GTM snippets:

<!DOCTYPE html>
<html lang="{{@site.locale}}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>{{meta_title}}</title>

    {{!-- Google Tag Manager --}}
    <script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
    new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
    j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
    'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
    })(window,document,'script','dataLayer','GTM-XXXXXXX');</script>
    {{!-- End Google Tag Manager --}}

    {{ghost_head}}
</head>
<body class="{{body_class}}">
    {{!-- Google Tag Manager (noscript) --}}
    <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXXX"
    height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
    {{!-- End Google Tag Manager (noscript) --}}

    <div class="site">
        {{{body}}}
    </div>

    {{ghost_foot}}
</body>
</html>

Step 3: Create GTM Partial (Optional)

For cleaner code organization, create partials/gtm.hbs:

{{!-- partials/gtm-head.hbs --}}
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXXX');</script>
<!-- End Google Tag Manager -->
{{!-- partials/gtm-body.hbs --}}
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->

Then include in default.hbs:

<head>
    {{> gtm-head}}
    {{ghost_head}}
</head>
<body>
    {{> gtm-body}}
    {{{body}}}
</body>

Step 4: Upload and Activate Theme

For Ghost(Pro):

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

For Self-Hosted:

ghost restart

Then activate via Settings → Design.

Basic GTM Configuration

Create GA4 Tag

Once GTM is installed, add your first tracking tag:

  1. In GTM, navigate to Tags → New
  2. Click Tag Configuration
  3. Select Google Analytics: GA4 Configuration
  4. Enter your Measurement ID (G-XXXXXXXXXX)
  5. Click Triggering
  6. Select All Pages
  7. Name the tag: "GA4 - Configuration"
  8. Click Save

Create Meta Pixel Tag

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

Publish Container

  1. Click Submit in the top-right
  2. Enter Version Name: "Initial GTM Setup - GA4 + Meta Pixel"
  3. Enter Version Description: "Added GA4 configuration and Meta Pixel base code"
  4. Click Publish

Testing and Validation

GTM Preview Mode

  1. In GTM, click Preview in the top-right
  2. Enter your Ghost site URL
  3. Click Connect
  4. New window opens with Tag Assistant
  5. Navigate your site and verify tags fire correctly
  6. Check:
    • GTM Container Loaded
    • GA4 Configuration tag fires on All Pages
    • Meta Pixel fires on All Pages

Verify dataLayer

Open browser DevTools → Console:

// Check if dataLayer exists
console.log(dataLayer);

// Should output: Array with GTM events

Tag Assistant Extension

  1. Install Google Tag Assistant Chrome extension
  2. Navigate to your Ghost site
  3. Click extension icon
  4. Verify:
    • GTM container loads
    • No errors or warnings
    • All tags configured correctly

Performance Optimization

Preconnect to GTM

Add to your theme's <head> before GTM script:

<link rel="preconnect" href="https://www.googletagmanager.com">
<link rel="dns-prefetch" href="//www.googletagmanager.com">

Async Loading Strategy

GTM loads asynchronously by default. For additional control:

// Delay GTM load until after page fully loads
window.addEventListener('load', function() {
  // GTM loads here
});

Tag Priority

In GTM, set tag firing priority:

  1. Edit any tag
  2. Click Advanced Settings
  3. Set Tag firing priority (higher numbers fire first)
  4. Critical tags (e.g., consent): Priority 100
  5. Analytics tags: Priority 50
  6. Marketing pixels: Priority 10

Ghost-Specific GTM Configuration

Environment Triggers

Create triggers for Ghost content types:

Trigger: Blog Posts Only

  • Trigger Type: Page View
  • Trigger fires on: Some Page Views
  • Condition: Page Path - contains - /blog/ (or your Ghost post URL structure)

Trigger: Homepage Only

  • Trigger Type: Page View
  • Trigger fires on: Some Page Views
  • Condition: Page Path - equals - /

Trigger: Member Portal

  • Trigger Type: Custom Event
  • Event name: portal-open

Variable Configuration

See GTM Data Layer for Ghost for complete variable setup.

Common Issues

GTM Container Not Loading

  • Verify Container ID - Check GTM-XXXXXXX is correct
  • Code Placement - Ensure head snippet is in <head>, body snippet at top of <body>
  • Ad Blockers - Test in incognito without extensions
  • CSP Headers - Check Content Security Policy allows GTM domains

dataLayer Undefined

  • Load Order - GTM script must load before any dataLayer.push() calls
  • Syntax Errors - Check browser console for JavaScript errors
  • Cache Issues - Clear Ghost cache or wait for CDN refresh

Tags Not Firing

  • Preview Mode - Use GTM Preview to debug
  • Triggers - Verify triggers are configured correctly
  • Publish Status - Ensure container is published, not just saved
  • Blocking - Check if browser extensions block tags

Performance Degradation

  • Too Many Tags - Limit number of tags in container
  • Heavy Custom HTML - Optimize custom scripts
  • Synchronous Tags - Use async loading where possible
  • Tag Priority - Set priorities to control load order

Ghost(Pro) vs. Self-Hosted

Ghost(Pro)

  • Code Injection: Recommended method (no theme upload required)
  • CDN Caching: GTM container cached by Cloudflare
  • Limitations: No server-side GTM (requires self-hosted)
  • SSL: Automatic HTTPS

Self-Hosted

  • Full Control: Direct theme file editing
  • Server-Side GTM: Can implement Google Tag Manager Server-side
  • Custom Variables: Access to server environment variables
  • Advanced Caching: Control Nginx/Varnish cache for GTM

Next Steps