Skip to content

Instantly share code, notes, and snippets.

@zjeaton
Last active March 28, 2024 14:34
Show Gist options
  • Star 36 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save zjeaton/42246742cdaf2fb46400d04c2eba9a8a to your computer and use it in GitHub Desktop.
Save zjeaton/42246742cdaf2fb46400d04c2eba9a8a to your computer and use it in GitHub Desktop.
Google Analytics 4 (with Measurement ID) in Hugo

Google Analytics 4 in Hugo

Blog post with slightly more detail can be found here. If you want to just get to it, read on.

I (very) recently decided to reimplement GA in my site, and found that existing implementation in Hugo was not compatible with GA4's new Measurement ID. This is an easy way to drop your Measurement ID into your site. I'm not going to go into how to sign up for GA.

This implementation requires that you create a site parameter for analytics, create a partial, and call the partial. I tweaked the names of the parameters and files so they didn't collide with the built-in hugo code.

Place the GoogleAnalyicsID (Measurement ID) in config.toml within [params].

# Google Analytics 4
googleAnalyticsID = "G-00000XXXXX"

Create the partial, analytics-gtag.html, and place it in /layouts/partials. Code below.

Call the partial just after the <head> tag in /layouts/_default/baseof.html.

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

That's it. It appears that this will be fixed in gohugo shortly, but for now this is a serviceable workaround.

<!-- 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>
@rufusdenne
Copy link

rufusdenne commented Feb 26, 2021

Really nice writeup and example @zjeaton – thanks for putting this together.

In case it help anyone else (or your implementation) I added {{ if and (hugo.IsProduction) (.Site.Params.googleAnalyticsID) }} to the conditional statement so that I don't track / post all my development activity to GA.

<head>
  {{ if and (hugo.IsProduction) (.Site.Params.googleAnalyticsID) }}
  {{ partial "analytics-gtag.html" . }}
  {{ end }}
  ...
 </head>

IsProduction a relatively new Hugo function (March 2020) so you'll need to be running > Hugo 0.66.0.

@felleg
Copy link

felleg commented Apr 10, 2021

Thanks so much for this write-up! It completely solved my analytics issues.

@DavorLovric
Copy link

Thank you @zjeaton for this straight forward guide!
And also thank you @rufusdenne for a nice improvement.

@deepix
Copy link

deepix commented Jun 5, 2021

A quick note that I had to capitalize "G" in config.toml - "GoogleAnalyticsID" - for it to work. The .md above needs this fix.

@brightzheng100
Copy link

brightzheng100 commented Jun 7, 2021

I guess this might depend on the theme as well.

For example, as I'm using Clarify theme, when I was trying to refer to the hack @zjeaton provides, I realized that, after checking out the code Clarify theme has, there is no such a need at all to make any further change: I just updated the param of ga_analytics = "G-XXXXXX" and it worked perfectly fine with GA4's MEASUREMENT ID.

For your convenience, I'd paste the the partial that the theme provides, as file of layout/partials/analytics.html:

{{- with .Site.Params.ga_analytics }}
<script async src="https://www.googletagmanager.com/gtag/js?id={{ . }}"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', '{{ . }}');
</script>
{{- end -}}
{{- with .Site.Params.baidu_analytics }}
<script>
  var _hmt = _hmt || [];
  (function() {
    var hm = document.createElement("script");
    hm.src = "https://hm.baidu.com/hm.js?{{ . }}";
    var s = document.getElementsByTagName("script")[0]; 
    s.parentNode.insertBefore(hm, s);
  })();
</script>
{{- end }}

{{- if (site.Params.plausible_analytics.enable) }}
<script async defer data-domain="{{ site.Params.plausible_analytics.websiteDomain }}" 
src='https://{{ default "plausible.io" site.Params.plausible_analytics.plausibleDomain }}/js/{{ default "plausible" site.Params.plausible_analytics.scritpName }}.js'>
</script>
{{- end }}

@sparkdoaz
Copy link

@brightzheng100
hugo server , localhost can test the GA4 ?
I want to look some data to verify !
thank you

@arnabsen1729
Copy link

This is amazing. Thanks a lot

@smoreface
Copy link

super straightforward, thank you! My theme (Etch) had a head.html instead of using baseof.html for the tags if anyone else runs into that.

@joshmenden
Copy link

Thanks!

@xiang0805
Copy link

hello guys,do I need to set the sitemap for the google search console if I want to use the GA4 in hugo that host on the github?

@nickdesaulniers
Copy link

Sounds like there's an "internal template" for this now in hugo, IIUC?
https://gohugo.io/templates/internal/#google-analytics

@cstpimentel
Copy link

Thanks a lot! :) Much appreciated, it was easy to follow.

@mafendi
Copy link

mafendi commented May 9, 2023

Thanks a lot!
Sorry for bothering you, do you have maybe some working solution for Cookie Consent (for Hugo)?

@marsavela
Copy link

Sounds like there's an "internal template" for this now in hugo, IIUC? https://gohugo.io/templates/internal/#google-analytics

Shouldn't this be used more than everybody creating their own?

@ChlorisF
Copy link

Thanks for the tutorial! In the more recent version of Hugo academic, there aren't layouts/partials or any file related to html... I added the internal template, and tweaked for Google Analytics ID in params.yaml but Google still doesn't receive any data. Could you have a look when you have time? Many thanks! Below is the default template for Hugo academic.
https://github.com/ChlorisF/starter-hugo-academic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment