Google Analytics 4 Implementation in Hugo

When I finally decided to push the hugo version of this website live and overwrite the wordpress version, I made the decision to put Google Analytics on it. My wordpress site had been using Cloudflare DNS, and therefore had low level analytics for free through Cloudflare. It was enough for me. For the hugo deploy I went with Netlify and Netlify DNS. Not wanting to pay $9/month for Netlify analytics at that time, but still desiring some type of analytics, i went with GA as it is monetarily cost-free.

At the time of deploy, Hugo had not addressed the new Google Analytics 4 implementation. (It seems they are working on it, however.) GA4 uses a Measurement ID in place of the long-present Tracking ID. This Measurement ID is embedded in a website in a different way than the Tracking ID has been. I found a workaround by looking into the GA docs, and the implementation can be found in the Github Gist that I wrote or following along below.

Implementation

Everything is pretty straightforward. I changed the names of parameters and files to prevent crashing with hugo internal templates.

First, place the Measurement ID into the root config file.

1
2
3
4
5
config.toml

[params]
# Google Analytics 4
googleAnalyticsID = "G-00000XXXXX"

Next, a partial is needed to run the javascript. I pulled this straight from the Analytics site, where the code was generated with my Measurement ID embedded. I replaced my Measurement IDs with references to the googleAnalyticsID in .Site.Params.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
layouts/partials/analytics-gtag.html

<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id={{ .Site.Params.GoogleAnalyticsID }}"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', '{{ .Site.Params.GoogleAnalyticsID }}');
</script>

Lastly, the partial needs to be called within the head of every page in which you would like tracking. Google suggests that the script be placed directly after the opening head tag. I called the partial (with an if statement checking for the existence of googleAnalyticsID) in baseof.html so it is implemented sitewide.

1
2
3
4
5
6
7
8
layouts/_default/baseof.html

<head>
  {{ if .Site.Params.GoogleAnalyticsID }}
  {{ partial "analytics-gtag.html" . }}
  {{ end }}
  ...
</head>

That’s it. Like I said, pretty straightforward. Hope this can help someone out while we wait for it to be integrated into Hugo.


comments powered by Disqus