Install guide
Add website analytics to Hugo
layouts/_partials/head.html - and don’t edit the file inside themes/.
The tag goes in your head partial: layouts/_partials/head.html on Hugo 0.146 and later, or layouts/partials/head.html on a project built before that.
<script defer src="https://app.feasible.lol/js/fs-k7m2q4x5r3n6t2v5.js"></script>This site runs on Hugo, so this page is written from the same problem you’re having.
Steps
- Look in
layouts/for a head partial. If your project has one, paste the tag inside<head>and you’re done. - If it lives in your theme instead -
themes/<name>/layouts/_partials/head.html- copy it to the same path under your ownlayouts/first, then edit the copy. - Build and deploy.
Hugo looks in your project’s layouts/ before the theme’s, so the copy wins. That’s the supported way to change a theme’s markup.
Never edit the theme directory
If your theme is a git submodule or a Hugo module, editing files under themes/ works until the next git submodule update or hugo mod get -u, at which point your change is gone and your traffic stops. No error, no warning - just a flat line you spot a fortnight later.
Copy the partial up. It takes ten seconds and it’s permanent.
Which folder name
Hugo v0.146.0 reimplemented how templates are found, and layouts/partials became layouts/_partials. If your project predates that and hasn’t been migrated, use whichever folder your project already has - the one your theme is reading from. Don’t create the other one and wonder why nothing changed.
If there’s no head partial at all, the tag goes wherever your baseof.html opens <head>.
hugo server won't show you anything
localhost, and localhost is not counted. That’s not a broken install - it’s the reason your own work never pollutes your numbers. Verify on the deployed site.Two things Hugo sites get wrong
baseURL in production. If it’s still http://localhost:1313/ when you build, your canonical URLs and everything derived from them are wrong. That’s not a tracking problem - the script reports the browser’s real URL either way - but you’ll be reading a broken sitemap while you debug the wrong thing.
Apex and www. Register the hostname you serve. If www.yourdomain.com redirects to yourdomain.com, register the destination. Traffic arriving on the other one shows up on the ingestion health panel as hostname_not_allowed, with a one-click action to allow it.
Multilingual sites
One tag, one site, one snippet. Language variants are paths - /de/pricing/ - so they show up as separate rows in your pages report, and the visitor’s browser language is a dimension you can filter on. Nothing extra to configure.
Check it worked
Deploy, open the site in a normal browser window, and click through two or three pages. Then open Feasible.
You should show up under Real-time visitors. If you don’t, go to Site settings → Ingestion health. It counts every event that arrived and every one that was dropped, each with a named reason - unknown_site means the snippet is for a site you haven’t registered, hostname_not_allowed means the page is on a hostname that isn’t on your list.
The send a test event button there posts through the real public URL, so it exercises what a browser does.
A brand-new site takes about fifteen seconds before its first event is accepted, so give it that before changing anything.
Related: Jekyll, Astro, and the install docs.
Sources: Hugo - new template system overview, checked September 3, 2026.