Google Tag Manager on ButterCMS | OpsBlu Docs

Google Tag Manager on ButterCMS

How to install and configure Google Tag Manager on ButterCMS. Covers installation method, container setup, verification, and ButterCMS-specific...

For general GTM concepts, see Google Tag Manager Overview

Overview

ButterCMS is a headless CMS — it has no frontend rendering layer. GTM must be added to whatever frontend framework consumes the ButterCMS API (React, Next.js, Gatsby, Vue, Nuxt, etc.).

Prerequisites

Installation

Headless CMS — Frontend Framework Installation

Since ButterCMS is a headless CMS, it delivers content via API — it does not render HTML pages. GTM must be installed in whatever frontend framework consumes the ButterCMS API.

Where to add GTM: In your frontend app's index.html, _document.tsx (Next.js), gatsby-ssr.js (Gatsby), or equivalent entry file

Next.js

// pages/_document.tsx (Pages Router) or app/layout.tsx (App Router)
import Script from 'next/script';

export default function RootLayout({ children }) {
  return (
    <html>
      <head>
        <Script id="gtm" strategy="afterInteractive">
          {`(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>
      </head>
      <body>
        <noscript>
          <iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXXX"
            height="0" width="0" style={{display:'none',visibility:'hidden'}} />
        </noscript>
        {children}
      </body>
    </html>
  );
}

Gatsby

Install the official plugin:

npm install gatsby-plugin-google-tagmanager
// gatsby-config.js
module.exports = {
  plugins: [
    {
      resolve: 'gatsby-plugin-google-tagmanager',
      options: {
        id: 'GTM-XXXXXXX',
        includeInDevelopment: false,
      },
    },
  ],
};

Nuxt 3

// nuxt.config.ts
export default defineNuxtConfig({
  app: {
    head: {
      script: [
        {
          innerHTML: `(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');`,
        },
      ],
    },
  },
});

Static HTML / Vanilla SPA

Add the standard GTM snippets to your index.html:

<!-- 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 -->
<!-- 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) -->

Replace GTM-XXXXXXX with your actual Container ID in both snippets.

ButterCMS-Specific Considerations

ButterCMS doesn't serve HTML — your frontend framework does. If using SSR (Next.js, Nuxt), add GTM in the document head component. For SPAs, add to index.html and handle route changes via History Change triggers in GTM.

Verification

After installation, verify GTM is working:

  1. GTM Preview Mode — In GTM, click Preview, enter your site URL, and verify the container loads.
  2. Browser Console — Open DevTools (F12) and run console.log(window.google_tag_manager). You should see an object (not undefined).
  3. Network TabFilter for googletagmanager.com and verify gtm.js loads with a 200 response.
  4. Data Layer Check — Run console.log(window.dataLayer) to verify the data layer array exists.

SPA Route Changes

Since ButterCMS-powered sites typically use client-side routing, standard GTM page view tracking won't capture navigation after the initial load. In GTM, create a History Change trigger and use it alongside (or instead of) the All Pages trigger for your GA4 page view tag.

Next Steps