Skip to content

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

Nothing is loaded and nothing is sent. No banner appears.

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.

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.

  1. Sign up at plausible.io and add your site’s domain.

  2. Open your site’s Site settings → Site installation. The script shown there contains your script id, which starts with pa- (e.g. pa-AbC123).

  3. 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”.

  1. In Umami Cloud (or your own Umami), add a website with your domain.

  2. Open the website’s settings and copy its Website ID (a long id with dashes).

  3. In .env:

    Terminal window
    PUBLIC_UMAMI_WEBSITE_ID=0f1e2d3c-...
    UMAMI_ORIGIN=

    Leave UMAMI_ORIGIN empty for Umami Cloud. If you host Umami yourself, set it to your Umami’s address, e.g. https://umami.example.com.

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:

  1. 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.

  2. Open Settings → Project and copy the Project API key (also called project token). It starts with phc_.

  3. In .env:

    Terminal window
    PUBLIC_POSTHOG_KEY=phc_AbC123...
    PUBLIC_POSTHOG_HOST=https://us.i.posthog.com

    PUBLIC_POSTHOG_HOST is the US cloud by default. For the EU cloud set https://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_.

  1. In Google Analytics, create a property and a Web data stream for your domain.

  2. Copy the stream’s Measurement ID (G-…).

  3. In .env:

    Terminal window
    PUBLIC_GA_MEASUREMENT_ID=G-ABC123

The id must look like G- followed by letters and digits.

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-consent in local storage).
  • The footer gets a Cookie settings button that opens the banner again.

Plausible, Umami and PostHog never show the banner.

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.js and, on each page, a POST to /lumen/event.
  • Umami: a request to /lumen/u.js and POSTs 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 to posthog.com, and under Application → Cookies and Local storage no PostHog entry. In PostHog, Activity (or Events) shows the $pageview within a minute or so.
  • Google Analytics: the cookie banner appears. Nothing from googletagmanager.com loads 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 delete analytics-consent under Application → Local storage.

The tools may ignore visits from localhost, so judge your dashboards after deploying.

  1. In Vercel, Settings → Environment Variables: add the ids you use (and UMAMI_ORIGIN if you self-host Umami).
  2. Redeploy. The PUBLIC_ ids are written into the pages at build time.
  3. 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 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_123

The other tools keep working. Copy the id again from the tool and redeploy.

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