Product Analytics
Opt-in PostHog product analytics across every chmonitor surface — off by default, Do Not Track respected, cookieless, no session recording.
chmonitor can optionally send product analytics — automatic pageviews, autocaptured interactions (clicks, form submits), client- and server-side crashes, plus explicit conversion funnel events (signups, cluster connects, upgrades, checkouts) — to PostHog for the hosted SaaS product's growth/business side. It is OFF by default — a hard no-op — until you configure an analytics key.
Coverage spans every surface of chmonitor.dev: the dashboard
(dash.chmonitor.dev, incl. server/API crash capture), the docs site
(docs.chmonitor.dev), the landing site, and the blog.
This is a different system from Product Telemetry (anonymous, on-by-default, aggregate OSS instance telemetry to chmonitor's own collector) and from Self-Tracking (writes usage events to your own ClickHouse instance). Product analytics exists purely to measure the marketing/signup/upgrade funnel and is never required to run chmonitor.
Opt in — off by default
No key, no network call
Without CHM_ANALYTICS_KEY (dashboard) / VITE_ANALYTICS_KEY (docs) /
PUBLIC_ANALYTICS_KEY (landing + blog) set, none of this code makes a network
call, loads PostHog, or sets a cookie. Self-hosted instances stay completely
untouched by default.
| Variable | Surface | Purpose |
|---|---|---|
CHM_ANALYTICS_KEY | Dashboard (derives client VITE_ANALYTICS_KEY; also read server-side for crash capture) | PostHog project key. Empty = disabled. |
CHM_ANALYTICS_HOST | Dashboard (derives client VITE_ANALYTICS_HOST) | PostHog ingestion host. Empty = PostHog Cloud (US). |
VITE_ANALYTICS_KEY | Docs site (TanStack Start) | PostHog project key. Empty = disabled. |
VITE_ANALYTICS_HOST | Docs site (TanStack Start) | PostHog ingestion host. Empty = PostHog Cloud (US). |
PUBLIC_ANALYTICS_KEY | Landing + blog (Astro) | PostHog project key. Empty = disabled. |
PUBLIC_ANALYTICS_HOST | Landing + blog (Astro) | PostHog ingestion host. Empty = PostHog Cloud (US). |
Both *_HOST variables let you point at a self-hosted PostHog instance
instead of PostHog Cloud, keeping the whole stack self-hostable in spirit.
Do Not Track
The browser navigator.doNotTrack
signal is checked before analytics initializes — when set, init is skipped
entirely. The dashboard additionally honors the cross-tool DO_NOT_TRACK/
VITE_DO_NOT_TRACK convention already used by telemetry.
Events
Landing site
| Event | When it fires |
|---|---|
landing_view | The marketing home page (/) loads |
pricing_view | The /pricing page loads |
cta_click | A tracked call-to-action link is clicked (target = a static identifier, e.g. hero-primary) |
Dashboard
| Event | When it fires |
|---|---|
signup | A Clerk account created within the last 2 minutes loads the app (approximates "just signed up") |
cluster_connect | A ClickHouse connection is added and saved |
sample_cluster_connected | The "Try with sample ClickHouse" read-only preset is connected |
sample_to_real_converted | A non-sample host is added after the sample was connected |
first_chart_render | The first chart renders with real data (once per page load) |
agent_message | A message is sent to the AI agent |
upgrade_click | An "Upgrade" call-to-action is clicked |
checkout_started | A Polar checkout session is created, right before redirect |
What is captured
- Automatic pageviews and pageleaves on every surface (SPA route changes included)
- Autocaptured interactions — clicks and form submissions (PostHog autocapture)
- Crashes — client-side React error boundaries report a
$exception; the dashboard Worker additionally reports server/API exceptions via PostHog's stateless/capture/endpoint (the Worker runs on workerd, so it cannot useposthog-node) - Explicit funnel events — the typed events listed above
What is still NOT collected
- Session recordings —
disable_session_recording: trueon every surface - No
identify()is ever called with a user-derived id — every distinct id stays PostHog's anonymous default - Explicit dashboard events are redacted defensively before leaving the process,
reusing the same
redactPropsallowlist Product Telemetry uses (drops any prop whose key implies sensitive content, or whose value looks like an email/IP/URL); server-side crash props are redacted the same way
Autocapture can record clicked-element text
Because autocapture is enabled, PostHog may record the text of clicked elements. The two safety rails that keep self-hosted instances silent are unchanged: it is off unless a key is set, and the browser Do Not Track signal disables it entirely.
PostHog is configured cookieless (persistence: 'localStorage'), so no cookie
banner is required for this feature.
Anonymous by design
No call site ever calls PostHog's identify() with anything user-derived —
every distinct id stays PostHog's anonymous default.