How to Configure Self-Hosted Plausible Analytics in Hugo

The plausible-hugo module routes analytics traffic to your private Plausible server when you set the selfhosted_domain parameter in your Hugo configuration.

The divinerites/plausible-hugo repository provides a lightweight integration for Hugo static sites. By adding a single configuration key, you can redirect all tracking requests from the public Plausible cloud to your own self-hosted instance without modifying any template code.

Setting the Self-Hosted Domain Parameter

Add the selfhosted_domain key under the [params.plausible] table in your site configuration. This value overrides the default plausible.io endpoint and tells the module where to load the analytics script from.

According to the README documentation (lines 443-452), the minimal configuration requires three values: enable, domain (your site identifier), and selfhosted_domain (your server address).

[params.plausible]
  enable            = true
  domain            = "my-site.example.com"
  selfhosted_domain = "myplausible.example.com"
  debug             = true  # Optional: load script during hugo server

When selfhosted_domain is present, the module generates script URLs pointing to https://myplausible.example.com/js/script.js instead of the default Plausible CDN.

How the Template Handles Self-Hosted Instances

The routing logic resides in layouts/partials/plausible_head.html. At lines 9-13, the partial checks site.Params.plausible.selfhosted_domain. If this parameter exists, it assigns the value to the $pio_domain variable, overriding the default domain.

The script URL assembles using four template variables: $pio_http, $pio_domain, $pio_js, and $pio_script. When selfhosted_domain is configured, the final output constructs as {{ $pio_http }}{{ $pio_domain }}{{ $pio_js }}{{ $pio_script }}.js, producing a fully qualified URL to your private server.

The partial also respects the plausible_do_not_track front matter flag and only injects the script when site.Params.plausible.enable equals true.

Including the Analytics Partial

Ensure your site's <head> section includes the partial. Most Hugo themes load this through layouts/partials/head.html or a similar base template.

<!DOCTYPE html>
<html>
<head>
    {{ partial "plausible_head.html" . }}
</head>
<body>
    <!-- page content -->
</body>
</html>

When Hugo renders the page, the partial outputs a deferred script tag and preconnect link pointing to your self-hosted domain:

<link rel="preconnect" href="https://myplausible.example.com">
<script defer data-domain="my-site.example.com"
        src="https://myplausible.example.com/js/script.js"></script>

Excluding Specific Pages from Tracking

Disable analytics on individual pages by adding plausible_do_not_track to the front matter. The partial checks for this flag at line 50 and skips script injection when present.

---
title: "Privacy Policy"
plausible_do_not_track: true
---

Summary

  • Set selfhosted_domain in [params.plausible] to override the default plausible.io endpoint
  • The partial layouts/partials/plausible_head.html automatically rebuilds the script URL using your domain (lines 9-13)
  • Enable debug = true during testing to force script loading in development mode
  • Use plausible_do_not_track: true in page front matter to exclude specific pages from analytics

Frequently Asked Questions

Do I need to modify template files to use self-hosted Plausible?

No. The layouts/partials/plausible_head.html partial automatically detects the selfhosted_domain configuration and switches the endpoint. You only need to update your config.toml file, keeping all template code unchanged.

What happens if I omit the selfhosted_domain parameter?

If selfhosted_domain is not set, the module defaults to plausible.io and loads the script from the public Plausible Analytics CDN. Your site ID (the domain parameter) functions identically regardless of which server hosts the analytics.

Can I use debug mode with a self-hosted instance?

Yes. Set debug = true under [params.plausible] to force the script to render even when running hugo server. This allows you to verify that the generated <script> tag points to your self-hosted domain before deploying to production.

Does the self-hosted configuration support all Plausible script extensions?

Yes. Whether you enable outbound link tracking, file downloads, or other extensions via additional configuration flags, the partial appends these parameters to the script URL generated for your self-hosted domain. The query-string logic remains identical to the public cloud version.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →