prelo
Plugins / Plausible analytics

Plausible analytics

Privacy-first analytics with a stats card on the Studio dashboard.

Jgithub.com/jverdeyenIntegrationsprelo >= 0.3Updated Apr 2026
Use this plugin
1
2
or point your agent at the spec:
Your agent reads the spec and writes the code into your project. Review the diff like any change.

What this adds

Visitor analytics without the consent-banner baggage: Plausible's lightweight, cookie-free script on every public page, and — if your Studio is ejected — a small stats card (visitors this week, top pages) on the dashboard so the site owner never has to log into a second tool.

Works with plausible.io (paid) or a self-hosted Plausible instance — say which in your project. Nothing here phones home from the CMS itself.

How it works

The tracking script goes in the frontend layout, keyed by domain from an env var. For the dashboard card, a custom route proxies the Plausible Stats API server-side, so the API key stays out of the browser; the ejected Studio fetches that route with the owner's existing session.

The spec your agent followsexpand ▾
You are wiring Plausible into a Prelo project. Env vars: `PLAUSIBLE_DOMAIN` (the site's domain as registered in Plausible), optional `PLAUSIBLE_HOST` (default `https://plausible.io`, set for self-hosted), and `PLAUSIBLE_API_KEY` (Stats API key — only needed for the dashboard card).

1. **Tracking script.** In the frontend's shared layout/head, when `PLAUSIBLE_DOMAIN` is set, add:

   ```html
   <script defer data-domain="{PLAUSIBLE_DOMAIN}" src="{PLAUSIBLE_HOST}/js/script.js"></script>
   ```

   Render it on public pages only — never in Studio, never on preview/draft routes. When the env var is missing, render nothing (the site must not 500 or warn in the browser).

2. **Outbound + 404 tracking (optional, ask the user).** Use `script.outbound-links.js` / `script.404.js` variants if wanted; document the extra goal setup Plausible requires in a code comment.

3. **Stats proxy route.** In `cms.config.js` `routes:`:

   ```js
   "GET /plausible-stats": async (req, res, db) => { /* … */ }
   ```

   - Refuse unless the request carries an authenticated Studio session or an API key of role viewer+ — check how other authenticated surfaces resolve the principal in this project rather than rolling your own check; if custom routes can't see the session cleanly, require an `Authorization: Bearer` API key.
   - Fetch from `{PLAUSIBLE_HOST}/api/v1/stats/aggregate?site_id={PLAUSIBLE_DOMAIN}&period=7d&metrics=visitors,pageviews` and `/api/v1/stats/breakdown?...&property=event:page&limit=5` with `Authorization: Bearer {PLAUSIBLE_API_KEY}`.
   - Cache the combined result in memory for 10 minutes (analytics doesn't need freshness; Plausible rate-limits).
   - Respond `{ visitors, pageviews, topPages: [{page, visitors}] }`. `503` with a clear message when env vars are missing.

4. **Dashboard card.** Only if the project has an **ejected Studio** (`prelo eject studio` — a `studio/` source tree in the repo): add a card to the dashboard screen matching the existing card styles — "Last 7 days": visitors + pageviews figures and the top-5 pages list, fetching `/api/x/plausible-stats` with the session. Handle the 503 by rendering a one-line "Add PLAUSIBLE_API_KEY to see stats here" hint. If the Studio is not ejected, skip this step and tell the user the card needs an ejected Studio (the stock Studio intentionally has no runtime plugin system).

5. **Verify.** Load a public page and confirm the script tag and a `/api/event` beacon to the Plausible host; hit the stats route authenticated and unauthenticated; confirm no Plausible request contains cookies.

After it's built

The owner sees traffic where they already work. Plausible's own dashboard remains available for deep dives; the card links to it. Removing PLAUSIBLE_DOMAIN turns the whole thing off cleanly.