Set up Plausible goals and custom events on a self-hosted instance from the terminal
By Flavio
Add pageview goals and custom events on your self-hosted Plausible, send the event from the site, and register it with plausible-setup.
Pageviews tell you which URL got the visit. A goal counts a chosen action: opening the thank-you page, clicking Create account, or completing a signup. Choose which one you mean before naming the event. On Plausible those are two different goal types, a pageview goal and a custom event.
This assumes the server is already yours. How to self-host Plausible analytics is the install, and Updating self-hosted Plausible Analytics using AI is how a Community Edition instance that sat still for years gets brought up to date. Community Edition has no Cloud Sites API, so Plausible Automation Toolkit talks to the dashboard you already log in to. The command is plausible-setup.
The commands below use shop.example.com as the tracked site and plausible.example.com as the Plausible server. Replace them with your own domains.
What you need
Plausible Automation Toolkit runs on macOS with Python 3.10 or newer, plus the system security and expect commands. You need an account on your own self-hosted Plausible Community Edition instance. Codex is optional. The CLI works from the terminal on its own.
After purchasing it, download the source zip from your Polar receipt and unzip it. Open Terminal in that folder and point the installer at your instance:
./install.sh --plausible-url https://plausible.example.com
That origin is the Plausible server. The tracked domain, shop.example.com, is a separate setting. The installer puts plausible-setup in ~/.local/bin and the Codex skill in ~/.codex/skills/setup-plausible. Store the dashboard login next:
plausible-setup credentials
The login, the Stats API key, and the site goal tokens go into the macOS login Keychain, not into the project.
The tracker has to be on the site before a goal can record anything. From the site’s source directory, preview the snippet and then apply it:
plausible-setup setup --dry-run
plausible-setup setup
The dry run shows the domain, the layout file and the tracker change it would make. Running it again does not add a second snippet. If it cannot pick a layout, pass --target with the file that contains </head>. Commit and deploy that change the way you usually ship the site.
List the goals, then add a pageview goal
A pageview goal counts visits to a path. Plausible already records the pageview, so the site’s code stays as it is. Pageview goals are the right tool for a thank-you page or an order confirmation page.
List what the site already has:
plausible-setup goals-list --domain shop.example.com
The first goal command needs a site-scoped plugin token. The CLI prints the dashboard URL for that token and asks for it in the terminal. Paste it at the prompt. It is stored in Keychain. Keep it out of the repo, out of shell history, and out of a chat with an agent.
Add the thank-you page. The quotes matter because of the asterisk:
plausible-setup goal-add --domain shop.example.com --page '/thank-you*'
The pathname has to match the path you see in the Plausible dashboard. An asterisk matches a pattern, and it can sit at either end or in the middle, so /thank-you* covers /thank-you and /thank-you/order-18. You should now see that goal in goals-list, and at the bottom of the dashboard once someone hits a matching path.
Send a custom event from the site
A custom event is for an action that does not have its own URL. A button click is the usual one. Creating the goal does not add this code. The site has to send the event, and the goal name has to match what the site sends, including capitals.
First check the tracker. The toolkit currently inserts /js/script.js. On installations using the legacy tracker, class-based events need the tagged-events extension. Replace that script URL with /js/script.tagged-events.js on your own Plausible host; keep its defer and data-domain attributes. For a newer site-specific tracker, use the snippet supplied by your instance’s installation screen. Do not load both snippets. Plausible’s release notes describe the legacy extension and the newer tracker.
The simplest trigger is a class on the element. This made-up button counts an attempt to start signup:
<button class="plausible-event-name=Signup+Click">Create account</button>
If the button already has a class, add this one after a space. A space in the event name is a + in the class, so plausible-event-name=Button+Click is the goal Button Click, not Button+Click. Custom event tracking is the full write-up of that class, including what to do when a site builder rewrites the = sign.
For a completed signup, call the function after your backend confirms success:
plausible('Signup')
A click on the button can still end in a validation error or a failed request, so in a form handler the call goes after the success check and before any redirect. Here form is your form element and /api/signup accepts its form data:
const response = await fetch('/api/signup', {
method: 'POST',
body: new FormData(form),
})
if (!response.ok) {
throw new Error(`Signup failed: ${response.status}`)
}
if (typeof window.plausible === 'function') {
window.plausible('Signup')
}
If your API returns HTTP 200 for an application error, check its JSON result too before firing the event. The typeof check lets the signup go through when the tracker is blocked. Keep the email address out of the event name and properties.
That name, Signup, is the goal. Register it after the site can send it:
plausible-setup goal-add --domain shop.example.com --event Signup
Plausible receives events sent before the goal exists, but it doesn’t backfill them: the counter starts at the moment you add the goal. Complete a signup once after that, on a deployed page, and the Signup goal should show a conversion. If you also want the button-click metric, register a separate goal with --event 'Signup Click'.
Read the goals back
A traffic report includes goals along with visitors, visits, pageviews, bounce rate, visit duration, top pages, and sources:
plausible-setup report --domain shop.example.com --period 30d --compare previous
The first report creates a Stats API key through the dashboard session and saves it in Keychain. Add --format markdown or --format json when you want the numbers in a file or a script. text and csv are the other two formats.
doctor is the check that changes nothing:
plausible-setup doctor --domain shop.example.com
It looks at the instance, the tracker endpoint, the project snippet, the site property, the Stats API, and the goal token if you have one. It checks the snippet in your repo, not the deployed page, so open the live site too.
Hand a goal to Codex
The installer also drops a Codex skill in ~/.codex/skills/setup-plausible. With that installed you can ask for a named goal and keep the token out of the chat:
Add a custom event goal named Signup for shop.example.com.
The site already sends that event after the signup API confirms success.
Don't put the API token in the chat or in the repo.
The skill chooses the action. The CLI asks for the site token at the terminal prompt.
If something looks wrong
If the custom event goal stays at zero, compare the goal name to the event name one character at a time. Button+Click in the class is the goal Button Click. Then trigger the event once more after goal-add.
If the browser shows no request, the class is missing or the tracker script is not on that page. In the Network tab, trigger the button and look for a request to /api/event on your Plausible host. Then run doctor for the snippet and the tracker endpoint. Two requests for one signup mean two tracker snippets, or a click handler and a success handler sending the same name. Plausible’s docs also say a request from localhost, or from a staging domain that is not on the site, is a common reason the event is dropped.
If goal-add stops to ask for a token, that is the site-scoped plugin token, not your dashboard password. Open the URL it prints, create the token there, and paste it at the prompt. credentials is the separate command for the dashboard login, when the instance itself rejects you.
If a pageview goal stays at zero, the pathname doesn’t match the path in the dashboard. /thank-you* does not match a page that lives at /account/thanks.
If your shell says plausible-setup: command not found, add ~/.local/bin to PATH and open a new terminal. python3 --version should print 3.10 or newer.
Get Plausible Automation Toolkit
Install trackers, report traffic and manage goals on your own Plausible Community Edition instance. Includes a macOS CLI, Codex skill and MIT source.
See Plausible Automation Toolkit → · Read the docs · $20 including tax, with full source code.
Want me to talk about your product? You can sponsor this site.