How to Integrate Plausible-Hugo with Multilingual Sites: Complete Configuration Guide

Plausible-Hugo integrates seamlessly with multilingual Hugo sites by reading per-language parameters from site.Params.plausible, automatically inheriting global settings when language-specific values are absent.

The divinerites/plausible-hugo module leverages Hugo's native multilingual architecture to deliver analytics across language versions without code duplication. Because the module reads configuration directly from the site's parameter table, it respects language-specific overrides while maintaining global defaults, allowing you to track all languages under one Plausible domain or configure distinct settings per locale.

Architecture of Plausible-Hugo Multilingual Support

The module determines which configuration to apply by evaluating the current language context through Hugo's site.Language object, merging parameters according to Hugo's standard inheritance hierarchy.

Core Components

Component Function Location Multilingual Behavior
plausible_head.html Generates the <script> tag, preconnect links, CSP helpers, and custom goal bootstrap layouts/partials/plausible_head.html Reads site.Params.plausible.* for the active language. Emits script only if enable is true and the page lacks plausible_do_not_track.
plausible_check.html Validates configuration and displays console reminder layouts/partials/plausible_check.html Shows GitHub star hint only for default language (site.Language == site.Sites.Default.Language).
plausible_js.html User-defined custom goals and event functions layouts/partials/plausible_js.html Supports language-specific goal names via .Site.Language.Lang.
i18n catalogue Translation strings for console messages i18n/en.toml, i18n/fr.toml Add <lang>.toml files for additional languages using the plausible_gitstar key.

Language Parameter Inheritance

Hugo merges language-specific params with global params using a hierarchical lookup. When rendering a French page, Hugo resolves site.Params.plausible.enable in this order:

  1. [languages.fr.params.plausible] (language-specific override)
  2. [params.plausible] (global default)
  3. Module defaults

This inheritance allows you to define common settings once globally while overriding specific values—such as disabling tracking for a particular language—without duplicating the entire configuration block.

Step-by-Step Configuration for Multilingual Sites

1. Define Languages in config.toml

Configure your multilingual structure with language blocks. The defaultContentLanguage establishes which language serves as the default for the console reminder and fallback parameters.

defaultContentLanguage = "en"

[languages]
  [languages.en]
    languageName = "English"
    weight = 1

  [languages.fr]
    languageName = "Français"
    weight = 2

  [languages.de]
    languageName = "Deutsch"
    weight = 3

2. Configure Per-Language Plausible Parameters

Add the params.plausible table under each language block to control tracking per locale. Global settings act as defaults.

[params.plausible]
  enable = true
  domain = "example.com"
  outbound_link = true

[languages]
  [languages.en]
    languageName = "English"
    weight = 1
    [languages.en.params.plausible]
      enable = true
      # Inherits domain from global params

  [languages.fr]
    languageName = "Français"
    weight = 2
    [languages.fr.params.plausible]
      enable = true
      # You can override domain here if using language-specific domains

  [languages.de]
    languageName = "Deutsch"
    weight = 3
    [languages.de.params.plausible]
      enable = false  # Disables tracking for German pages

3. Insert the Partial Template

Include the Plausible head partial in your base layout. The same partial serves all languages automatically by reading the current language's parameters.

<!-- layouts/_default/baseof.html -->
<!DOCTYPE html>
<html lang="{{ .Site.Language.Lang }}">
<head>
    <meta charset="UTF-8">
    <title>{{ .Title }}</title>
    {{ partial "plausible_head.html" . }}
</head>
<body>
    {{ block "main" . }}{{ end }}
</body>
</html>

The plausible_head.html partial evaluates site.Params.plausible.enable for the current language context, ensuring the analytics script only loads for languages where tracking is enabled.

4. Add Internationalization Strings

Create i18n files for each supported language to translate the console reminder. Copy the existing structure from i18n/en.toml or i18n/fr.toml.


# i18n/en.toml

[plausible_gitstar]
other = "*** Please consider leaving a star on GitHub if you like this Plausible-Hugo module.\n Remove this warning by adding `gitstar = false` in your Plausible configuration."

# i18n/fr.toml

[plausible_gitstar]
other = "*** Merci de laisser une étoile sur GitHub si vous aimez ce module Plausible-Hugo.\n Supprimez cet avertissement en ajoutant `gitstar = false` dans votre configuration Plausible."

The plausible_check.html partial displays this message only when site.Language matches site.Sites.Default.Language, preventing duplicate console messages across language versions.

5. Implement Language-Specific Custom Goals

Create layouts/partials/plausible_js.html to define custom event tracking that varies by language. Access the language code via .Site.Language.Lang.

{{- $lang := .Site.Language.Lang -}}

<script>
// Language-prefixed goal function
function trackDownload{{ $lang | upper }}() {
    plausible('Download{{ $lang | upper }}');
}

// Generic goal with language property
function trackContact() {
    plausible('Contact', {props: {language: '{{ $lang }}'}});
}
</script>

This approach generates distinct goal names (e.g., DownloadEN, DownloadFR) or passes language as an event property, enabling segmentation by language in your Plausible dashboard.

Key Implementation Details

How the Default Language Check Works

The plausible_check.html partial implements a strict equality check to limit the GitHub star reminder to the default language:

{{ if eq site.Language site.Sites.Default.Language }}
    {{ i18n "plausible_gitstar" | safeJS }}
{{ end }}

This comparison evaluates the current rendering context's language object against the default site language. If you require the console reminder for all languages, override this partial in your site's layouts/partials/plausible_check.html and remove the conditional wrapper.

Parameter Merging Behavior

Hugo resolves site.Params.plausible using a cascading lookup mechanism. For a French page (/fr/), the evaluation order is:

  1. site.Params.plausible from [languages.fr.params.plausible]
  2. site.Params.plausible from global [params.plausible]
  3. Internal module defaults

This inheritance allows you to set domain globally while toggling enable per language, or override the outbound_link setting for specific locales without repeating the entire configuration block.

Summary

  • Plausible-Hugo integrates with multilingual Hugo sites by reading per-language parameters from site.Params.plausible, automatically inheriting global settings when language-specific values are absent.
  • Configure each language in config.toml with [languages.xx.params.plausible] blocks to control tracking per locale, including enabling/disabling analytics or using different domains.
  • Include the single partial {{ partial "plausible_head.html" . }} in your base template; it automatically respects the current language's configuration.
  • Provide i18n translations via i18n/*.toml files for the console reminder, which displays only for the default language unless you override plausible_check.html.
  • Implement language-specific custom goals in layouts/partials/plausible_js.html using .Site.Language.Lang to segment events by language in your Plausible dashboard.

Frequently Asked Questions

Can I use different Plausible domains for different languages?

Yes. While most multilingual sites track all languages under one domain, you can override the domain parameter per language in your config.toml. For example, set [languages.fr.params.plausible] domain = "fr.example.com" while keeping the global domain as example.com. The plausible_head.html partial reads site.Params.plausible.domain for the current language context, so each language version will load the appropriate tracking domain.

Why does the GitHub star reminder only appear for the default language?

The plausible_check.html partial contains a conditional {{ if eq site.Language site.Sites.Default.Language }} that restricts the console message to the default language defined in defaultContentLanguage. This prevents duplicate console messages when users navigate between language versions. If you want the reminder to appear for all languages, copy the partial to your site's layouts/partials/plausible_check.html and remove the conditional wrapper while keeping the i18n lookup.

How do I test Plausible integration on a multilingual site locally?

Add debug = true to the params.plausible block of the specific language you want to test. For example, set [languages.en.params.plausible] debug = true in your config.toml. When running hugo server, the plausible_head.html partial will render the analytics script for that language even in development mode. Remember to remove the debug flag or set it to false before building for production to ensure accurate data collection.

Can I disable Plausible for specific languages only?

Yes. Set enable = false in the params.plausible block for any language you want to exclude. For example, to disable tracking for German while keeping it active for English and French, add [languages.de.params.plausible] enable = false to your configuration. The plausible_head.html partial checks site.Params.plausible.enable for the current language context and will skip rendering the analytics script for that language version, effectively disabling tracking for those pages.

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 →