How to Set Up 404 Error Tracking with Plausible-Hugo
Plausible-Hugo automatically fires a custom 404 event whenever a visitor lands on your Hugo 404 page by injecting a conditional script through the plausible_head.html partial.
Setting up 404 error tracking helps you monitor broken links and missing pages that visitors attempt to access. The Plausible-Hugo theme for Hugo static sites provides built-in support for tracking these errors as custom events in your Plausible analytics dashboard. This guide walks through the complete configuration process using the actual implementation in divinerites/plausible-hugo.
Configure the 404 Custom Goal in Plausible
Before your site can send 404 data, you must tell Plausible to expect a custom event named exactly 404.
- Open your Plausible dashboard and navigate to Settings → Goals.
- Click Add custom event.
- Enter
404as the event name (this string must match exactly). - Save the goal.
According to the repository documentation, "You only have to configure the goal in your Plausible settings… Select Custom event as the goal trigger and enter this exact name: 404"【^/cache/repos/github.com/divinerites/plausible-hugo/master/README.md†L194-L199】.
Enable Plausible-Hugo in Your Configuration
Add the required parameters to your site's config.toml (or hugo.toml) to enable the module and set your domain.
theme = ["plausible-hugo"]
[params.plausible]
enable = true
domain = "example.com" # Your Plausible domain ID
The enable parameter activates the tracking system, while domain identifies your site in Plausible analytics. The repository's README provides a "Minimum config.toml" example showing these essential settings【^/cache/repos/github.com/divinerites/plausible-hugo/master/README.md†L31-L38】.
Add the Plausible Head Partial to Your Layouts
Insert the Plausible head partial inside the <head> section of your base layout so it loads on every page, including 404 pages.
In your layouts/_default/baseof.html (or equivalent base template):
<!DOCTYPE html>
<html lang="{{ .Site.LanguageCode }}">
<head>
{{ partial "plausible_head.html" . }}
{{ block "head" . }}{{ end }}
</head>
<body>
{{ block "main" . }}{{ end }}
</body>
</html>
This partial call injects the Plausible tracking script and handles the conditional 404 event logic automatically.
How the 404 Tracking Works
The magic happens in layouts/partials/plausible_head.html. When Hugo renders a 404 page, the partial detects the page kind and injects a JavaScript call to record the event.
At lines 92-95 of the partial【^/cache/repos/github.com/divinerites/plausible-hugo/master/layouts/partials/plausible_head.html†L92-L95】:
{{- if eq .Page.Kind "404" }}
<script>plausible("404",{ props: { path: document.location.pathname } });</script>
{{- end }}
When .Page.Kind equals "404", the template renders the script tag that calls plausible("404") with the current path as a property. This sends the event to Plausible's API endpoint when the 404 page loads in the visitor's browser.
Optional Configuration for Self-Hosted or Proxied Setups
If you use a self-hosted Plausible instance or route traffic through a Netlify proxy, add the corresponding parameters to your configuration.
[params.plausible]
enable = true
domain = "example.com"
selfhosted_domain = "analytics.yourdomain.com"
proxy_netlify = true
The plausible_head.html partial reads these values at the top of the file (lines 4-46) to compute the correct script URL ($pio_domain), protocol ($pio_http), and data API endpoint ($pio_data_api)【^/cache/repos/github.com/divinerites/plausible-hugo/master/layouts/partials/plausible_head.html†L4-L46】.
Verify Your 404 Tracking Implementation
Test the integration before relying on the data in production.
- Deploy your site and visit a non-existent URL (e.g.,
/this-page-does-not-exist). - Open browser developer tools → Network tab → filter for "plausible".
- Look for a POST request to
https://<domain>/api/eventwith a payload containing"name":"404". - Check your Plausible dashboard under Events to confirm the
404goal is counting hits.
Summary
- Create a custom goal named exactly
404in your Plausible dashboard settings. - Enable tracking by setting
enable = trueanddomainin[params.plausible]insideconfig.toml. - Include the partial by adding
{{ partial "plausible_head.html" . }}to your base layout's<head>. - Automatic detection occurs when
layouts/partials/plausible_head.htmlchecks for.Page.Kind "404"and firesplausible("404", { props: { path: ... } }). - Self-hosted users should configure
selfhosted_domainorproxy_netlifyparameters for correct endpoint targeting.
Frequently Asked Questions
What exact name should I use for the custom goal in Plausible?
Use the string 404 (without quotes in the UI, but exactly those three characters). The event name is case-sensitive and must match the string passed to the plausible() function in layouts/partials/plausible_head.html at line 93.
Does the 404 tracking work with self-hosted Plausible instances?
Yes. Set the selfhosted_domain parameter in your [params.plausible] configuration block. The partial automatically adjusts the script source and API endpoint to point to your self-hosted domain instead of the cloud-hosted plausible.io service.
Why don't I see 404 events in my dashboard immediately?
Ensure you have completed both the dashboard configuration (creating the custom goal) and the code implementation (including the partial in your base layout). Also verify that you are visiting an actual 404 page recognized by Hugo (check that .Page.Kind equals "404"). Events may take a few minutes to appear in the Plausible interface.
Can I track the specific URLs that triggered 404 errors?
Yes. The implementation automatically includes the path as an event property: props: { path: document.location.pathname }. This allows you to see which specific URLs visitors attempted to access when they triggered the 404 error in your Plausible analytics.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →