Analytics
Each template can send page views and a few events to Plausible, Umami, PostHog, Google Analytics 4, or several of them at once. Each one stays off until you set its id.
Templates: all of them.
Services: Plausible, Umami (cloud or
self-hosted), PostHog (US or EU cloud, or self-hosted),
Google Analytics 4. Every template has all four
(a site made earlier gets it with npx wptom update).
| Tool | Cookies | Consent banner | Setting |
|---|---|---|---|
| Plausible | No | Not shown | PUBLIC_PLAUSIBLE_SCRIPT_ID |
| Umami | No | Not shown | PUBLIC_UMAMI_WEBSITE_ID (+ UMAMI_ORIGIN when self-hosted) |
| PostHog | No (set up without cookies or storage) | Not shown | PUBLIC_POSTHOG_KEY (+ PUBLIC_POSTHOG_HOST for the EU cloud or self-hosted) |
| Google Analytics 4 | Yes | Shown; GA loads only after “Accept” | PUBLIC_GA_MEASUREMENT_ID |
Without settings
Section titled “Without settings”Nothing is loaded and nothing is sent. No banner appears.
The first-party routes
Section titled “The first-party routes”Plausible, Umami and PostHog don’t load from their own domains. Your site serves their scripts and
forwards their data through its own routes, under the neutral path /lumen/:
| Route | What it does |
|---|---|
/lumen/script.js |
Plausible’s script, fetched from Plausible and cached for a day |
/lumen/event |
Forwards Plausible page views and events |
/lumen/u.js |
The Umami tracker |
/lumen/u/api/send |
Forwards Umami page views and events |
/lumen/ph/… |
PostHog’s script (/lumen/ph/static/array.js, cached for a day) and everything it sends |
So the browser only talks to your domain: ad blockers that block analytics domains don’t drop your visits, and there is no third-party request. The routes forward the visitor’s IP address and browser name so the tools can count unique visitors, as they would without the proxy. Each route answers “not found” while its tool is off.
Google Analytics loads directly from Google, and only after consent.
Events
Section titled “Events”Besides page views, the forms send events to every tool that is on:
| Event | When |
|---|---|
Contact message |
A contact or quote form was sent |
Signup (with the form’s source) |
A new address joined the newsletter, a waitlist or an interest list (not for an address already on the list) |
In Google Analytics they appear as contact_message and signup; in PostHog under their own
names, next to $pageview. In Plausible, add them as
goals (Site settings → Goals → Add goal → Custom event) to see them in the dashboard.
Plausible
Section titled “Plausible”-
Sign up at plausible.io and add your site’s domain.
-
Open your site’s Site settings → Site installation. The script shown there contains your script id, which starts with
pa-(e.g.pa-AbC123). -
In
.env:Terminal window PUBLIC_PLAUSIBLE_SCRIPT_ID=pa-AbC123
The id must start with pa-. With anything else, /lumen/script.js fails and the log shows
“Invalid Plausible script id”.
-
In Umami Cloud (or your own Umami), add a website with your domain.
-
Open the website’s settings and copy its Website ID (a long id with dashes).
-
In
.env:Terminal window PUBLIC_UMAMI_WEBSITE_ID=0f1e2d3c-...UMAMI_ORIGIN=Leave
UMAMI_ORIGINempty for Umami Cloud. If you host Umami yourself, set it to your Umami’s address, e.g.https://umami.example.com.
PostHog
Section titled “PostHog”PostHog is a product analytics tool (funnels, trends, dashboards). The template sets it up for privacy:
- No cookies, no local storage. posthog-js runs with
persistence: 'memory': nothing is stored in the visitor’s browser, so no consent banner is needed. The trade-off: PostHog can’t recognize a visitor from one page to the next or on a later visit, so every page load counts as a new anonymous visitor. Page view and event counts are exact; “unique users” and paths across pages are not available. - Loads after the page. The script is added only once the page has finished loading, from
your own domain (
/lumen/ph/static/array.js), so it doesn’t slow the page down or show up as a third-party request. - Autocapture is off. PostHog records page views and the template’s custom events
(
Contact message,Signup), not every click.
Set it up:
-
Sign up at posthog.com and pick the US or EU cloud (the EU cloud keeps your data in the EU). Create a project for your site.
-
Open Settings → Project and copy the Project API key (also called project token). It starts with
phc_. -
In
.env:Terminal window PUBLIC_POSTHOG_KEY=phc_AbC123...PUBLIC_POSTHOG_HOST=https://us.i.posthog.comPUBLIC_POSTHOG_HOSTis the US cloud by default. For the EU cloud sethttps://eu.i.posthog.com; for your own PostHog, its address. The link back to PostHog’s app follows the host automatically.
The key is public on purpose (PostHog’s project keys can only send data, not read it), which is
why it starts with PUBLIC_.
Google Analytics 4
Section titled “Google Analytics 4”-
In Google Analytics, create a property and a Web data stream for your domain.
-
Copy the stream’s Measurement ID (
G-…). -
In
.env:Terminal window PUBLIC_GA_MEASUREMENT_ID=G-ABC123
The id must look like G- followed by letters and digits.
Consent
Section titled “Consent”Google Analytics uses cookies, so in the EU and the UK you need the visitor’s consent first. With a measurement id set:
- A cookie banner appears on the first visit. Its texts are in Interface texts → Cookie banner, and it links to your privacy page.
- Until the visitor clicks Accept, Google’s script isn’t loaded at all, and Google Consent Mode starts with every signal set to “denied”.
- Accept loads GA and allows analytics storage only; advertising signals stay denied. Decline closes the banner and nothing loads.
- The choice is remembered in the visitor’s browser (
analytics-consentin local storage). - The footer gets a Cookie settings button that opens the banner again.
Plausible, Umami and PostHog never show the banner.
Try it on your computer
Section titled “Try it on your computer”After setting an id, restart npm run dev and open your site with the browser’s developer
tools on the Network tab:
- Plausible: a request to
/lumen/script.jsand, on each page, aPOSTto/lumen/event. - Umami: a request to
/lumen/u.jsandPOSTs to/lumen/u/api/send. - PostHog: after the page has loaded, a request to
/lumen/ph/static/array.js, then requests to other/lumen/ph/…addresses carrying the page view. Nothing toposthog.com, and under Application → Cookies and Local storage no PostHog entry. In PostHog, Activity (or Events) shows the$pageviewwithin a minute or so. - Google Analytics: the cookie banner appears. Nothing from
googletagmanager.comloads until you click Accept; then it does. Reload: no banner, GA loads directly. To see the banner again, use Cookie settings in the footer, or deleteanalytics-consentunder Application → Local storage.
The tools may ignore visits from localhost, so judge your dashboards after deploying.
Put it online
Section titled “Put it online”- In Vercel, Settings → Environment Variables: add the ids you use (and
UMAMI_ORIGINif you self-host Umami). - Redeploy. The
PUBLIC_ids are written into the pages at build time. - Visit the live site once, then look at the tool’s dashboard: Plausible and Umami show the visit within a minute or so; Google Analytics shows it under Reports → Realtime after you accept the banner. PostHog lists the page view under Activity.
A mistyped id
Section titled “A mistyped id”A Google Analytics id or PostHog key in the wrong form doesn’t break your site: that one tool is switched off and the build (or, on pages rendered on request, the server log) shows a warning such as:
[analytics] Google Analytics is off: Invalid GA4 measurement id: G-abc[analytics] PostHog is off: Invalid PostHog project key: phx_123The other tools keep working. Copy the id again from the tool and redeploy.
Troubleshooting
Section titled “Troubleshooting”| What you see | Why, and what to do |
|---|---|
[analytics] … is off in the build log, or “Invalid Plausible script id” in the log |
The id has the wrong form. Copy it again (G-…, phc_…, pa-…) without spaces or quotes |
| No PostHog requests at all | PUBLIC_POSTHOG_KEY isn’t set where the site was built (it’s written into the pages at build time: redeploy after adding it), or the key was switched off as mistyped (see above) |
/lumen/ph/static/array.js loads, but nothing arrives in PostHog |
PUBLIC_POSTHOG_HOST points at the other cloud: a project in the EU cloud needs https://eu.i.posthog.com |
| PostHog shows every page view as a new person | Expected: the template runs PostHog without cookies or storage, so visitors aren’t followed between pages |
/lumen/script.js answers 404 |
The id isn’t set where the site runs: restart npm run dev, or add it in Vercel and redeploy |
/lumen/script.js answers 502 |
Plausible didn’t return the script for that id. Check the id in Plausible’s Site installation |
| No visits in Google Analytics | GA loads only after Accept. Visitors who decline aren’t counted, by design |
| Umami counts nothing (self-hosted) | UMAMI_ORIGIN must be your Umami’s address without a trailing path |