Install Google Tag Manager on HubSpot | Blue Frog Docs

Install Google Tag Manager on HubSpot

Complete guide to installing and configuring Google Tag Manager on HubSpot CMS Hub.

Install Google Tag Manager on HubSpot

Google Tag Manager (GTM) provides a centralized platform to manage all your tracking tags on HubSpot without editing code repeatedly. This guide covers HubSpot-specific GTM implementation.

Why Use GTM on HubSpot?

Benefits Over Direct Code Implementation

  • Easier management: Update tags without editing HubSpot settings
  • Non-technical friendly: Marketers can add/modify tags independently
  • Centralized control: All tags in one platform
  • Better testing: Preview mode before publishing changes
  • Version control: Roll back to previous container versions
  • Better performance: Single container load vs. multiple scripts
  • Advanced features: Custom triggers, variables, and data layer

GTM vs. Direct HubSpot Implementation

Feature GTM Direct Code in HubSpot
Ease of updates Click and publish Edit Site Header HTML
Learning curve Medium Low
Flexibility Very High Medium
Multiple tags Easy Requires multiple code blocks
Team collaboration Built-in Must share HubSpot access
Testing Preview mode Production only

Prerequisites

  1. Google Tag Manager account - Create free at tagmanager.google.com
  2. HubSpot access - Settings access to modify Site Header HTML
  3. Super Admin or Website Editor - HubSpot permissions

Installation Methods

Install GTM globally on all HubSpot pages using Site Header HTML.

Step 1: Create GTM Container

  1. Go to Google Tag Manager
  2. Click Create Account (if new) or select existing account
  3. Fill in Account Name (e.g., "Your Company Name")
  4. Container Setup:
    • Container Name: Your website domain (e.g., "example.com")
    • Target Platform: Web
  5. Click Create
  6. Accept Terms of Service

Step 2: Copy GTM Container Code

After creating container, you'll see two code snippets:

Code Snippet 1 (Head):

<!-- 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-XXXXXX');</script>
<!-- End Google Tag Manager -->

Code Snippet 2 (Body):

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

Copy both snippets.

Step 3: Add GTM to HubSpot Site Header

  1. In HubSpot, go to Settings (gear icon)
  2. Navigate to WebsitePages
  3. Scroll to Site Header HTML
  4. Paste the first snippet (Head code) into Site Header HTML box
  5. Click Save

Your Site Header HTML should look like:

<!-- 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-XXXXXX');</script>
<!-- End Google Tag Manager -->

The noscript tag should go at the top of the <body>. Since HubSpot doesn't provide body-level code injection, add to Site Footer HTML instead:

  1. In same Settings → Website → Pages section
  2. Scroll to Site Footer HTML
  3. Paste the second snippet (noscript code)
  4. Click Save

Note: Footer placement means it won't fire if JavaScript is disabled, but this affects less than 1% of users.

Step 5: Verify Installation

  1. Visit your HubSpot website
  2. Open browser DevTools (F12)
  3. Go to Console tab
  4. Type: google_tag_manager
  5. Should return GTM object (not undefined)

Alternative verification:

  • Install Google Tag Assistant browser extension
  • Visit your site
  • Extension should show GTM container ID

Method 2: Custom Template Module (Advanced)

For multi-site HubSpot setups or granular control.

Create GTM Module

  1. Go to Design Tools in HubSpot
  2. Create New Module → "GTM Container"
  3. Add module code:
{% if module.container_id %}
<!-- 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','{{ module.container_id }}');</script>
<!-- End Google Tag Manager -->
{% endif %}
  1. Add module field:
{
  "id": "container_id",
  "name": "container_id",
  "label": "GTM Container ID",
  "type": "text",
  "default": "GTM-XXXXXX"
}
  1. Add module to template before </head>

Setting Up GTM After Installation

Create Your First Tag: GA4 Configuration

  1. In GTM, go to TagsNew
  2. Click Tag Configuration
  3. Choose Google Analytics: GA4 Configuration
  4. Enter Measurement ID (G-XXXXXXXXXX)
  5. Triggering: Select All Pages
  6. Name tag "GA4 - Configuration"
  7. Save

Create Data Layer Variables

To access HubSpot data in GTM:

  1. In GTM, go to VariablesNew
  2. Variable ConfigurationData Layer Variable
  3. Data Layer Variable Name: pageType
  4. Save as "Page Type"

See GTM Data Layer for HubSpot-specific data layer implementation.

Enable Built-In Variables

  1. In GTM, go to Variables
  2. Under Built-In Variables, click Configure
  3. Enable useful variables:
    • Page URL
    • Page Path
    • Referrer
    • Click URL
    • Click Text
    • Form Element

Publish Container

  1. Click Submit in GTM
  2. Version Name: "Initial setup - GA4"
  3. Version Description: "Added GA4 configuration tag"
  4. Click Publish

HubSpot-Specific GTM Configuration

Create HubSpot Custom Variables

Useful variables for HubSpot sites:

1. Contact ID Variable

function() {
  return '{{ contact.vid }}' !== '' ? '{{ contact.vid }}' : null;
}

2. Lifecycle Stage Variable

function() {
  return '{{ contact.lifecycle_stage }}' || 'unknown';
}

3. Content Type Variable

function() {
  return '{{ content.type }}' || 'page';
}

To create Custom JavaScript variables in GTM:

  1. VariablesNewUser-Defined Variables
  2. Choose Custom JavaScript
  3. Paste function code
  4. Save

Create HubSpot Event Triggers

Form Submission Trigger:

  1. TriggersNew
  2. Type: Custom Event
  3. Event name: hubspot_form_submit
  4. Save as "HubSpot Form Submission"

CTA Click Trigger:

  1. TriggersNew
  2. Type: Click - All Elements
  3. Fire on: Some Clicks
  4. Click Classes contains hs-cta OR Click Classes contains cta_button
  5. Save as "HubSpot CTA Click"

See Event Tracking for event listener code.

Testing GTM on HubSpot

Use GTM Preview Mode

  1. In GTM, click Preview (top right)
  2. Enter your HubSpot site URL
  3. Click Connect
  4. New tab opens with Tag Assistant connected
  5. Navigate your HubSpot site
  6. See which tags fire on each page

Verify Tags Fire Correctly

In Preview mode, check:

  • Tags Fired: Should see your GA4 config tag
  • Tags Not Fired: Should be empty (or expected)
  • Data Layer: Verify variables populated correctly

Debug Common Issues

GTM Not Loading:

// Check in browser console
console.log(window.google_tag_manager); // Should return object
console.log(dataLayer); // Should return array

Tags Not Firing:

  • Check trigger conditions
  • Verify container is published (not just preview)
  • Clear browser cache
  • Disable ad blockers

Advanced: Multiple GTM Containers

For complex setups (e.g., separate containers for dev/staging/prod):

Environment-Based Containers

{% if content.domain == 'www.yoursite.com' %}
  <!-- Production GTM -->
  <script>...GTM-PROD...</script>
{% elif content.domain == 'staging.yoursite.com' %}
  <!-- Staging GTM -->
  <script>...GTM-STAGING...</script>
{% else %}
  <!-- Development GTM -->
  <script>...GTM-DEV...</script>
{% endif %}

If absolutely necessary:

<!-- Primary GTM -->
<script>(function(w,d,s,l,i){...})(window,document,'script','dataLayer','GTM-XXXXXX');</script>

<!-- Secondary GTM (different dataLayer name) -->
<script>(function(w,d,s,l,i){...})(window,document,'script','dataLayer2','GTM-YYYYYY');</script>

Note: This can cause conflicts. Only use if teams manage separate containers.

Integrating GTM with HubSpot Analytics

Avoid Duplicate Tracking

With both HubSpot analytics and GTM:

  • HubSpot tracks natively: Page views, form submissions, CTA clicks
  • GTM tracks for external tools: GA4, Meta Pixel, etc.

Best practice: Accept both systems track the same events; use each for its strengths.

Pass HubSpot Data to GTM

Add to Site Header HTML (before GTM code):

<script>
  window.dataLayer = window.dataLayer || [];
  dataLayer.push({
    {% if contact %}
    'contactId': '{{ contact.vid }}',
    'lifecycleStage': '{{ contact.lifecycle_stage }}',
    'isContact': true,
    {% else %}
    'isContact': false,
    {% endif %}
    'pageType': '{{ content.type }}',
    'contentId': '{{ content.id }}',
    'pageName': '{{ content.name }}'
  });
</script>

<!-- Then GTM code -->
<script>(function(w,d,s,l,i){...})</script>

See GTM Data Layer for complete implementation.

Performance Optimization

Async Loading (Already Default)

GTM loads asynchronously by default:

j.async=true;

Defer Non-Critical Tags

In GTM, for non-critical tags:

  1. Edit tag
  2. Advanced SettingsTag firing options
  3. Choose Once per page (instead of unlimited)

Monitor Performance Impact

Use PageSpeed Insights:

  1. Test page with GTM
  2. Check "Reduce JavaScript execution time"
  3. Verify GTM not blocking render

See Performance Troubleshooting for optimization.

Common GTM Tags for HubSpot

1. GA4 Configuration Tag

  • Tag Type: Google Analytics: GA4 Configuration
  • Trigger: All Pages
  • Purpose: Initialize GA4 tracking

2. GA4 Event Tag - Form Submissions

  • Tag Type: GA4 Event
  • Event Name: generate_lead
  • Trigger: HubSpot Form Submission
  • Purpose: Track form leads

3. Meta Pixel Tag

  • Tag Type: Custom HTML
  • Trigger: All Pages
  • Purpose: Facebook/Instagram advertising

See Meta Pixel Setup.

4. LinkedIn Insight Tag

  • Tag Type: Custom HTML
  • Trigger: All Pages
  • Purpose: LinkedIn advertising

5. Hotjar Tracking Code

  • Tag Type: Custom HTML
  • Trigger: All Pages
  • Purpose: User behavior analytics

Troubleshooting

GTM Container Not Loading

Symptoms: Tags don't fire, Preview mode can't connect

Check:

  1. Container ID is correct (GTM-XXXXXX format)
  2. Code is in Site Header HTML (not footer)
  3. HubSpot settings have been saved
  4. No JavaScript errors blocking GTM load
  5. Ad blocker disabled (for testing)

Debug:

// In browser console
console.log(google_tag_manager); // Should return object
console.log(google_tag_manager['GTM-XXXXXX']); // Your container ID

Preview Mode Can't Connect

Issue: "Tag Assistant" can't connect to site

Solutions:

  1. Disable browser extensions (especially privacy/ad blockers)
  2. Use incognito/private browsing
  3. Clear browser cache
  4. Ensure you're on the correct domain
  5. Check HubSpot domain is published and accessible

Tags Fire in Preview But Not Production

Cause: Container not published

Fix:

  1. In GTM, check top right corner
  2. Should say "Latest Workspace Changes Published"
  3. If not, click SubmitPublish

Data Layer Variables Return Undefined

Cause: Data layer not pushed before GTM loads

Fix: Ensure data layer code comes BEFORE GTM code:

<!-- Data Layer first -->
<script>
  window.dataLayer = window.dataLayer || [];
  dataLayer.push({...});
</script>

<!-- Then GTM -->
<script>(function(w,d,s,l,i){...})</script>

Next Steps

For general GTM concepts, see Google Tag Manager Guide.

// SYS.FOOTER