Hugo Analytics Without Cookies
Add Fusionaly to a Hugo site in your head partial, only in production builds. No cookies, and track links with a shortcode.
In Hugo, you add the Fusionaly script to the partial that holds <head>. With hugo.IsProduction, it loads in your built site and not in hugo server.
Before you start
You need a Fusionaly server, with your site's domain added as a website. Fusionaly takes events only from the domains you added. See Installation.
In the examples, replace analytics.example.com with the domain of your Fusionaly server.
Add the script
-
Find the file of your theme that holds
<head>, oftenthemes/<theme>/layouts/partials/head.html. Some themes have a file for your own additions, such asextend_head.htmlin PaperMod. -
Copy the file to the same path under the
layouts/folder of your project. Hugo uses your copy instead of the theme's file. -
Add the script to your copy:
layouts/partials/head.html {{ if hugo.IsProduction }}<script defer src="https://analytics.example.com/y/api/v1/sdk.js"></script>{{ end }}
hugo builds in the production environment, and hugo server runs in development. So your local previews are not counted.
Page changes
Hugo builds static pages, and each one is a full page load. Fusionaly counts each page without any setup.
Track events
Fusionaly counts page views and button clicks without any setup. To give an event your own name,
use the data-fusionaly-event-name attribute. See Tracking.
In templates, add the attribute to the HTML. Hugo does not output raw HTML from Markdown by default. For a tracked link in a post, make a shortcode:
<a href="{{ .Get "href" }}" data-fusionaly-event-name="{{ .Get "event" }}">{{ .Inner }}</a>Then use it in Markdown:
{{< track-link href="/download/" event="download_clicked" >}}Download{{< /track-link >}}Check that it works
- Open your site in a normal browser window. Fusionaly skips automated browsers, such as Playwright, and browsers that send Do Not Track.
-
In the developer tools, open the network tab, and find a
POSTrequest to/x/api/v1/events. A 403 status means that your site's domain is not added as a website. - Open your Fusionaly dashboard. The visit shows up within about a minute.
Notes
- In Hugo 0.146 and later, the folders are
layouts/_partials/andlayouts/_shortcodes/. The old paths still work.
Next steps
- Revenue Tracking: count purchases and their amounts.
- Section Tracking: count the sections that visitors see.
- Exclude your own visits: stop counting your own browser.
- AI Clients (MCP): ask Claude Code, Codex, or Cursor about your traffic.
Guides for other frameworks: Next.js, React, Astro, Nuxt, SvelteKit, WordPress, Shopify, Webflow, Ghost, and the generic guide.