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:

  1. Open the content file (Markdown or HTML) for the page you want to track.

  2. Add the plausible_custom_goal parameter to the front matter:

    ---
    title: "About Us"
    plausible_custom_goal: "AboutPageVisit"
    ---
  3. Build your site with hugo and deploy.

  4. 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_goal to any page's front matter to enable automatic goal tracking on page entry.
  • Template-driven injection: The layouts/partials/plausible_head.html partial handles JavaScript injection and wrapper definition without manual coding.
  • Safe execution: A queue-based window.plausible wrapper 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.

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:

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 →