Google Tag Manager in Next.js

The app I'm currently working on is bootstrapped using Next.js and needs to implement Google Tag Manager. The task was assigned to me, but Google's "Quick Start Guide" for GTM wanted me to do this:

"Copy the following JavaScript and paste it as close to the opening tag as possible on every page of your website, replacing GTM-XXXX with your 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.jsid='+i+dl;f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer','GTM-XXXX')</script>
<!-- End Google Tag Manager -->

And also this:

"Copy the following snippet and paste it immediately after the opening tag on every page of your website, replacing GTM-XXXX with your container ID:"

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

If you know a little more about React development than I do after four months, you can instantly spot that following these instructions very literally is going to require you to use dangerouslySetInnerHTML to force React to use this inline script in the <head> of the page. The reason this attribute is named so verbosely and alarmingly is that incautious use of it opens a site up to a cross-site scripting attack.

I didn't know this, so I had to spend five minutes searching to find it out. Still, when I did, I immediately started looking around for a more React-friendly alternative. (Google's own docs were strangely silent on the issue.) Further searching produced this module, but its examples weren't very helpful:

import React from 'react'
import ReactDOM from 'react-dom'
import Router from 'react-router'
import routes from './routes'

...
import TagManager from 'react-gtm-module'

const tagManagerArgs = {
  gtmId: 'GTM-000000'
}

TagManager.initialize(tagManagerArgs)
...

const app = document.getElementById('app')
ReactDOM.render(<Router routes={routes} />, app)

When you read documentation for almost anything based on React you see things like this all the time, and when you're an Extremely Junior DeveloperTM it can be very frustrating because you never mount an app the way those last two lines suggest when you're using the common bootstrappers like create-react-app or Next.js. Since you only barely understand how any of this works, you can feel very uncertain about how to adapt this code to your own actual app. And what are those ellipses hiding? I'd like to see that code, please.

So from my experience as that Extremely Junior Developer, this just looked like we were tossing an initialize method into a random location where it would never get called. I had to dig around for quite some time to find this Next.js GitHub issue that provided a helpful example, not for Google Tag Manager, but for Google Analytics. Fortunately, the poster explicitly said that it would work for "other ga tools"

My needs were slightly simpler than the poster's, so here's the code I ended up with ("XXXXXXX" here represents whatever your GTM ID might be), in the _app.js file of my NextJS installation:

import App, { Container } from 'next/app'
import React from 'react'
import './app.css'
import TagManager from 'react-gtm'

const tagManagerArgs = {
  id: 'GTM-XXXXXXX'
}

class MyApp extends App {
  componentDidMount () {
    TagManager.initialize(tagManagerArgs)
  }

  render () {
    const { Component, pageProps } = this.props
    return (
      <Container>
        <Component {...pageProps} />
      </Container>
    )
  }
}

export default MyApp

A couple notes:

  1. If you don't have an _app.js file in your Next app, here's what that's all about.
  2. I didn't actually end up using the module I mentioned above, but this fork of it, which seemed like it was a little more up-to-date.

Hopefully this helps some young developer who felt just as lost as I did when I was trying to solve this problem.

New Setup

IMAGE.JPG

I’ve always  wanted to own an Apple Display. This one is used, from eBay, and it’s the same resolution at 24” as my laptop screen at 17”, so the clarity isn’t amazing—particularly by comparison with the 4K display right next to it. But it still feels nice and looks nice on my desk. 

This setup also fulfills another long-term wish: To have my monitor mounted on an arm, off the surface of my desk. I had to do a little extra rigging with a block of wood to make the clamp for this dual-arm mount attach to my weird metal-frame desk (see below), but it looks great and gives me a lot of maneuverability. 

IMAGE.JPG

Now to get to work. 

How the New Deal Actually Worked

The government can spend taxpayer money on the Green New Deal (and it should), but direct spending is not the only option, and if the New Deal is a good guide, not even the most important option. 

Some really interesting economic history in here that I didn’t know.