Analytics

Google Analytics, Meta Pixel and privacy-friendly alternatives

Hugolify ships with ten analytics services: Google Analytics and Meta Pixel, both wired to the cookie banner, and eight alternatives, most of them cookieless and loaded without consent.

Which one

ServiceCookiesLicenseHostingFree plan
Google AnalyticsYesProprietarySaaSYes
Meta PixelYesProprietarySaaSYes
UmamiNoMITSaaS or self-hostedCloud Hobby: 1 site, 100k events/month
PlausibleNoAGPL-3.0SaaS or self-hostedSelf-hosted only (Community Edition)
MatomoOptionalGPL-3.0SaaS or self-hostedSelf-hosted only (On-Premise)
SelineNoProprietarySaaSNo, 7-day trial
FathomNoProprietarySaaSNo, 7-day trial
GoatCounterNoEUPL-1.2SaaS or self-hostedYes, for reasonable use
Simple AnalyticsNoProprietarySaaS5 sites, 30-day history
CabinNoProprietarySaaS1 site, 10k pageviews/month

Self-hosting Umami, Plausible, Matomo and GoatCounter is free: you only pay for the server.

Free plans as of October 2026. Check the vendor’s pricing page before choosing.

How it works

  • Production only: every service, Google Analytics and Meta Pixel included, is rendered when hugo.IsProduction is true. hugo server and --environment staging builds are never tracked.
  • Consent: Google Analytics and Matomo with cookies: true wait for the analytics category of the cookie banner, Meta Pixel for the marketing category. The other services are cookieless and load without consent.
  • Build checks: an enabled service with a missing required parameter fails the build. A service whose banner or consent category is disabled is not loaded, and the build warns.
  • Overrides: each service has its own partial, /layouts/partials/footer/analytics/<service>.html. Override it for options the configuration does not expose (SPA mode, tags, exclusions…).

A plain hugo build runs in production. On Netlify, deploy previews built with hugo -b $DEPLOY_PRIME_URL are tracked too, unless the service restricts the hostnames, like Umami domains.

Google Analytics

Setup

/config/_default/services.yaml

googleAnalytics:
  id: "G-XXXXXXXXXX"

This is the native Hugo service configuration.

Google Analytics needs the cookie banner: without it, the build warns and the ID is ignored. In CookieConsent mode, it also needs cookieconsent.analytics.

Enable the banner

See Cookie banner for the full banner reference.

/config/_default/params.yaml

cookie_banner:
  enable: true # Required
  cookieconsent:
    enable: true # Use CookieConsent
    analytics: true # Required to load Google Analytics

Behaviours

The banner has two modes, and each one loads Google Analytics differently.

Simple bannerCookieConsent
cookieconsent.enablefalsetrue
Required to load GAcookie_banner.enablecookieconsent.analytics
Consent Mode v2NoYes
Preferences modalNoYes
Consent cookiecookie-consent (31 days)cc_cookie
On acceptgtag with anonymize_ipanalytics_storage: granted
On refuse_ga* cookies deletedTracking disabled, _ga* cookies erased
Meta PixelNoYes

In CookieConsent mode, nothing is sent before a choice is made: consent defaults to denied for every storage type, with ads_data_redaction on and url_passthrough on.

Meta Pixel

Meta Pixel is an advertising tracker, so it waits for the marketing category of CookieConsent, not analytics.

/config/_default/params.yaml

analytics:
  meta:
    pixel_id: "000000000000000" # Required
cookie_banner:
  enable: true # Required
  cookieconsent:
    enable: true # Required
    marketing: true # Required to load Meta Pixel

It is listed as a separate service in the advertisement section of the preferences modal. The simple banner is not supported: without CookieConsent and the marketing category, the build warns and the pixel is not loaded.

There is no <noscript> fallback pixel, because it would be sent before any consent.

Other services

Configuration

Every other service is configured under analytics, like Meta Pixel. A service is enabled by its block, or by true when it needs no parameter. An empty block ({}) is ignored.

/config/_default/params.yaml

analytics:
  umami:
    website_id: "94db1cb1-74f4-4a40-ad6c-962362670409"
  cabin: true

Several services can run side by side, for example while comparing two of them.

Migrating from scripts.html

If you added Plausible, or any other service below, in /layouts/partials/footer/scripts.html following a previous version of this page, remove it when you enable the service under analytics. Otherwise the script loads twice.

Umami

Open source analytics with a simple dashboard: visits, page views, referrers and events. Umami Cloud is hosted in the US and the EU.

analytics:
  umami:
    website_id: "94db1cb1-74f4-4a40-ad6c-962362670409" # Required
    url: "" # Self-hosted script URL, defaults to https://cloud.umami.is/script.js
    domains: "" # Comma-separated hostnames allowed to send data

domains keeps deploy previews and staging hosts out of your statistics, for example example.com,www.example.com.

Plausible

Lightweight, open source and privacy-first. Plausible Cloud is hosted in the EU.

analytics:
  plausible:
    script_id: "pa-XXXXXXXX" # Site settings > General > Site installation
    url: "" # Self-hosted instance URL, defaults to https://plausible.io

script_id loads the script Plausible generates for your site. It is the recommended setup since October 2025.

Legacy script

The previous script, with a data-domain attribute, still works but Plausible no longer recommends it. Use it when your instance does not provide a per-site script yet, or to send stats to several dashboards at once. It applies when script_id is not set.

analytics:
  plausible:
    domain: "" # Defaults to the baseURL hostname
    url: "" # Full script URL, defaults to https://plausible.io/js/script.js

The build fails when the domain resolves to an empty value, for example with a baseURL of /.

domain has to match the site registered in Plausible, www. included. A baseURL of https://www.example.com/ gives www.example.com, not example.com. Set it explicitly when the two differ.

Matomo

The most complete service on this page, Cloud or self-hosted. Matomo Cloud is hosted in Frankfurt.

analytics:
  matomo:
    url: "https://matomo.example.com" # Required, instance URL
    site_id: "1" # Required
    cookies: false # Optional, see below
cookies: false (default)cookies: true
CookiesNone (disableCookies)_pk_*
ConsentNot requiredCookieConsent analytics category
LoadedOn every pageAfter consent
On refuseNothing to clean_pk_* cookies erased

With cookies: true, Matomo needs the CookieConsent mode of the cookie banner:

cookie_banner:
  enable: true
  cookieconsent:
    enable: true
    analytics: true

Without CookieConsent, with the simple banner or no banner at all, the build warns and Matomo is not loaded.

Seline

Privacy-first and cookieless, hosted in the EU.

analytics:
  seline:
    token: "PROJECT_TOKEN" # Required, project settings

Fathom

Privacy-focused and cookieless, SaaS only, with an EU isolation option.

analytics:
  fathom:
    site_id: "ABCDEFG" # Required

GoatCounter

Open source and cookieless. The hosted version is free for personal sites and small businesses, and you can self-host it.

analytics:
  goatcounter:
    code: "yoursite" # Hosted, https://yoursite.goatcounter.com
    endpoint: "" # Self-hosted count endpoint, takes precedence over code
    src: "" # Self-hosted script URL, defaults to https://gc.zgo.at/count.js

code or endpoint is required. Set src too and nothing is loaded from goatcounter.com or zgo.at.

Simple Analytics

Cookieless and collects no personal data. Hosted in the Netherlands.

analytics:
  simpleanalytics: true

No identifier: declare your domains in the Simple Analytics dashboard. A <noscript> pixel is rendered for visitors without JavaScript.

Cabin

Cookieless, with a lightweight script and carbon reporting. Data is stored in the EU.

analytics:
  cabin: true

No identifier: declare your domain on the Domains page of the Cabin dashboard.

Documentation