# How to Configure Self-Hosted Plausible Analytics in Hugo

> Easily configure self-hosted Plausible analytics for your Hugo site. Use the plausible-hugo module and set selfhosted_domain in your Hugo config for private traffic routing.

- Repository: [divinerites/plausible-hugo](https://github.com/divinerites/plausible-hugo)
- Tags: how-to-guide
- Published: 2026-02-28

---

**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).

```toml
[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`](https://github.com/divinerites/plausible-hugo/blob/main/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`](https://github.com/divinerites/plausible-hugo/blob/main/layouts/partials/head.html) or a similar base template.

```html
<!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:

```html
<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.

```yaml
---
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`](https://github.com/divinerites/plausible-hugo/blob/main/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`](https://github.com/divinerites/plausible-hugo/blob/main/layouts/partials/plausible_head.html) partial automatically detects the `selfhosted_domain` configuration and switches the endpoint. You only need to update your [`config.toml`](https://github.com/divinerites/plausible-hugo/blob/main/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.