How to Track Custom Goals by Page Entry with Plausible-Hugo
To track custom goals by page entry in Plausible-Hugo, add a plausible_custom_goal parameter to your page's front matter, and the theme automatically injects a JavaScript call to plausible() when the page loads.
The divinerites/plausible-hugo theme integrates Plausible Analytics into Hugo static sites through declarative front-matter configuration. By leveraging Hugo's templating system, the theme enables per-page custom event tracking without requiring manual JavaScript insertion or server-side code.
How Plausible-Hugo Implements Custom Goal Tracking
The theme uses a three-layer architecture to fire custom goals on page entry: front-matter detection, template injection, and JavaScript wrapper protection.
Front Matter Configuration
The entry point for custom goal tracking is the page's front matter. You define the goal name using the plausible_custom_goal parameter, which accepts any string value:
---
title: "Contact"
plausible_custom_goal: "ContactPageVisit"
---
The parameter supports Hugo's templating syntax, allowing dynamic goal names based on page variables:
---
title: "Product Details"
plausible_custom_goal: "product_{{ .File.BaseFileName }}_view"
---
Template Injection Logic
The layouts/partials/plausible_head.html partial (lines 80-89) checks for the front-matter flag using Hugo's with conditional:
{{ with .Params.plausible_custom_goal }}
plausible('{{ . | safeJS }}');
{{ end }}
When plausible_custom_goal exists, the partial injects a JavaScript snippet into the page's <head> that calls plausible() with the specified goal name. The safeJS filter ensures proper escaping while preserving the string value.
The JavaScript Wrapper
To prevent errors if the main Plausible script hasn't loaded, the partial defines a generic wrapper before the custom goal call:
window.plausible = window.plausible || function() {
(window.plausible.q = window.plausible.q || []).push(arguments)
}
This queue-based pattern ensures that custom goal events are captured even if the Plausible library loads asynchronously or after the page entry event fires.
Step-by-Step Implementation
To implement custom goal tracking on a specific page:
-
Open the content file (Markdown or HTML) for the page you want to track.
-
Add the
plausible_custom_goalparameter to the front matter:--- title: "About Us" plausible_custom_goal: "AboutPageVisit" --- -
Build your site with
hugoand deploy. -
Verify in the generated HTML that the
<head>contains:<script> /* Manage custom goals by entering a page */ /* if parameter "plausible_custom_goal" is set */ plausible('AboutPageVisit'); </script>
The goal will now fire automatically each time a visitor loads the page, appearing in your Plausible dashboard under the specified event name.
Advanced Usage with Dynamic Goal Names
For sites with multiple similar pages (such as product catalogs or documentation sections), you can use Hugo's page variables to generate unique goal names per page while maintaining a consistent naming pattern:
---
title: "Enterprise Plan"
plausible_custom_goal: "pricing_{{ .File.BaseFileName }}_view"
---
When Hugo renders this page, it converts {{ .File.BaseFileName }} to the filename (e.g., "enterprise"), resulting in a goal named pricing_enterprise_view. This allows you to track individual page performance within category-level aggregated data.
Summary
- Declarative configuration: Add
plausible_custom_goalto any page's front matter to enable automatic goal tracking on page entry. - Template-driven injection: The
layouts/partials/plausible_head.htmlpartial handles JavaScript injection and wrapper definition without manual coding. - Safe execution: A queue-based
window.plausiblewrapper ensures events capture even if the analytics script loads asynchronously. - Dynamic support: Hugo templating within the front-matter value allows per-page unique goal names using variables like
{{ .File.BaseFileName }}.
Frequently Asked Questions
How do I verify that my custom goal is firing correctly?
Check the generated HTML source of your deployed page for the JavaScript snippet containing plausible('YourGoalName'). You can also use your browser's Network tab to filter for requests to plausible.io/api/event and verify the payload contains your custom goal name in the name field.
Can I track multiple custom goals on a single page entry?
The current implementation in plausible_head.html supports a single custom goal per page through the plausible_custom_goal parameter. To track multiple events, you would need to customize the partial to iterate over a slice of goals or manually inject additional JavaScript in your page template using plausible_js.html.
Does the custom goal tracking work with outbound link tracking enabled?
Yes, the custom goal functionality operates independently of other Plausible features. The plausible_head.html partial includes the custom goal JavaScript alongside the standard Plausible script initialization, so outbound link tracking (configured via plausible_outbound_links parameter) and custom goals can function simultaneously without conflict.
What happens if I use a goal name with special characters or spaces?
The partial applies the safeJS filter to the goal name value: {{ . | safeJS }}. This ensures proper JavaScript escaping while preserving the string content. However, Plausible Analytics recommends using simple alphanumeric characters and underscores for goal names to ensure consistent reporting in the dashboard. Avoid quotes or backslashes in the front-matter value to prevent template rendering issues.
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 →