Static site generators · 3 min setup

How to add analytics to a Hugo site

To add VisitTrack to Hugo, render the script tag in your theme's head partial — or in the theme's "extend head" hook, such as PaperMod's extend_head.html — wrapped in {{ if hugo.IsProduction }} so hugo server never sends data. Put the site id in your site config so the theme files stay untouched.

Updated

Hugo merges your project's layouts folder over the theme's, so you never edit the theme itself: create a file with the same name in your own layouts folder and Hugo uses yours. Hugo 0.146 renamed the partials folder to layouts/_partials/; on older versions and many themes it's layouts/partials/. Use whichever your Hugo version and theme use.

Hugo at a glance

Where the tag goes
A head partial or the theme's head hook (e.g. extend_head.html)
Production only
{{ if hugo.IsProduction }} (false under hugo server)
Config
params.visitrack.siteId in hugo.toml
Goals
A small shortcode adding data-vt-goal
Hosting
Any static host — Netlify, Cloudflare Pages, GitHub Pages, Vercel

How to install VisitTrack on Hugo

  1. Step 1: Copy your site id into hugo.toml

    Copy the id from VisitTrack's install step and add it to your site config. Keeping it in config means the partial works across environments and themes.

    hugo.toml
    [params.visitrack]
      siteId = "SITE_ID"
  2. Step 2: Create the partial

    hugo.IsProduction is true for hugo builds (the production environment) and false for hugo server. Hugo escapes the attribute value for you.

    layouts/_partials/visitrack.html
    {{ if hugo.IsProduction }}
      {{ with site.Params.visitrack.siteId }}
        <script defer data-site="{{ . }}" src="https://visitrack.app/tracker.js"></script>
      {{ end }}
    {{ end }}
  3. Step 3: Include it in the head

    If your theme has a head hook, put the include there — PaperMod reads extend_head.html, and many themes have a similar hook (check your theme's docs). Otherwise copy the theme's head.html (or the <head> part of baseof.html) into your own layouts folder and add the line before </head>.

    layouts/_partials/extend_head.html (PaperMod)
    {{ partial "visitrack.html" . }}
  4. Step 4: Build and deploy

    Run hugo (or let your host build it), deploy, and open the live site.

How to check VisitTrack is working on Hugo

  1. Search the generated public/index.html for tracker.js after a production build — it should be there; under hugo server it shouldn't.
  2. Open the deployed site and read two posts; the VisitTrack live view shows you and the Pages tab lists both paths.
  3. Your theme's 404.html usually has "404" or "not found" in its title, so broken links show up as page_not_found events automatically.

Hugo output is plain static HTML, so every page is a full page load and one pageview. Taxonomy pages (/tags/go/), section lists and paginated lists (/posts/page/2/) each have their own path.

If your theme uses a client-side page-transition library that changes the URL with the History API, those navigations are counted too — no theme changes needed.

How to track custom events and goals in Hugo

Markdown links can't carry custom attributes in Hugo, so add a shortcode that renders a link with data-vt-goal and use it in your content. (Shortcodes live in layouts/_shortcodes/ on Hugo 0.146+, layouts/shortcodes/ before.)

Shortcode + usage
<!-- layouts/_shortcodes/goal.html -->
<a href="{{ .Get "href" }}" data-vt-goal="{{ .Get "name" }}">{{ .Inner }}</a>

<!-- in any post -->
{{< goal href="https://app.example.com/signup" name="blog_signup_click" >}}Try it free{{< /goal >}}

To measure how many readers finish a post, add <div data-vt-scroll="post_finished"></div> near the end of your single.html template. It fires once per page when that element is half visible. Then make either event a goal in Settings → Goals.

Script options you might need on Hugo

All optional — add them to the same tag. Full reference: script configuration.

AttributeWhat it does
data-cookielessStore nothing in the browser; the server derives a daily-rotating id. See cookieless mode.
data-exclude="/app/*"Never track these paths (comma-separated, * wildcard). Checked on every navigation.
data-allow-localTrack on localhost and *.local — for testing an install only.
data-debugLog every event the script sends, and why it skipped one, to the console.
data-auto="false"Turn off automatic events (downloads, contact clicks, form submits, rage clicks, JS errors, 404s).

Hugo troubleshooting

The tag isn't in the built HTML

Either the partial isn't included from the head your theme actually renders, or the build ran in a non-production environment (hugo --environment staging). Check hugo.IsProduction and the include path.

Your override is ignored

The file must mirror the theme's path and name exactly, in your project's layouts folder, using the same partials folder name (_partials vs partials) your Hugo version resolves.

Deploy previews count as traffic

Netlify and Cloudflare previews build in production mode too. Save your real domain under Settings → General → Allowed hostnames in VisitTrack.

site.Params.visitrack.siteId is empty

Config keys are case-insensitive in Hugo but the nesting matters: it must be under [params.visitrack].

Hugo analytics FAQ

Where do I put an analytics script in Hugo?

In the head of your base template — ideally through a partial included from your theme's head hook (like PaperMod's extend_head.html), so you don't modify the theme. Wrap it in hugo.IsProduction to skip local development.

Does hugo server send analytics data?

Not with the partial above: hugo.IsProduction is false under hugo server. VisitTrack's script also ignores localhost by default.

Does VisitTrack work with Hugo themes like PaperMod or Blowfish?

Yes. It's one tag in the page head, independent of the theme. Use the theme's head-extension partial if it has one, or override its head template in your own layouts folder.

Can I track outbound links on a Hugo blog?

Yes, automatically. Every click on a link to another domain is recorded and shows up in the Outbound tab, with no shortcode needed.

Is VisitTrack a privacy-friendly alternative to Google Analytics for Hugo?

Yes. In cookieless mode it stores nothing in the browser, so a static blog can skip the consent banner. See VisitTrack vs Google Analytics.

Keep going

Add VisitTrack to your Hugo site

Cookie-free analytics with revenue attribution, live visitors, funnels and session replays. One script tag, every feature on every plan. 14 days free, no card required.

Not on Hugo? See all 29 integration guides.