Adding Google Analytics to a Next.js blog the old-fashioned way

2023-06-25

First meaningful commit on the blog after the initial Vercel template clone. I wanted Google Analytics on the site, and I wanted it wired up the minimum-dependency way — no react-ga package, no wrappers, just the gtag script tag and a small helper module.

What landed

  • lib/ga.js — two functions. googleAnalyticsPageView(url) calls gtag('config', ID, { page_path: url }) so SPA navigations are tracked. googleAnalyticsEvent({ action, params }) is a wrapper around gtag('event', ...) for anything custom I want to fire later.
    // log the pageview with their URL
    export const googleAnalyticsPageView = (url) => {
      window.gtag('config', process.env.NEXT_PUBLIC_GOOGLE_ANALYTICS, {
        page_path: url,
      })
    }
     
    // log specific events happening.
    export const googleAnalyticsEvent = ({ action, params }) => {
      window.gtag('event', action, params)
    }
  • pages/_document.js — a custom Next.js Document that injects the gtag.js script and the initial gtag('config', …) call into the <head> of every page.
  • tsconfig.json — explicitly includes the new pages/_document.js and lib/ga.js so the TypeScript compiler doesn't miss them in the build. (This is the Next.js / TS interplay bit that I always forget: mixing .js into an otherwise-.tsx project needs explicit includes.)
  • .env — deleted. It only held IS_TEMPLATE=true from the template, which is no longer true.

The NEXT_PUBLIC_ env var

NEXT_PUBLIC_GOOGLE_ANALYTICS is the env var that holds the measurement ID. The NEXT_PUBLIC_ prefix is Next's mechanism for exposing env vars to the browser bundle — anything without that prefix stays server-side. For an analytics ID that's fine (it's literally designed to be visible in the page source), but it's worth noting: if the ID ever needed to be private, this is not where it would go.

Not yet working

This PR lands the plumbing but I haven't verified data is actually flowing to the GA dashboard yet. That's going to surface a small issue in a few PRs — namely that this is Universal Analytics, not GA4, and UA is about to be sunset. PR #3 migrates to GA4.


PR: https://github.com/StevieIsmagic/vercel_blog/pull/1