Documentation
Analytics (PostHog)
PostHog product analytics — client and server tracking, events, and the analytics dashboard.
Motoko Base uses PostHog for product analytics. PostHog is separate from Sentry (errors) — do not mix them.
Official docs: PostHog documentation
Setup
- Create a PostHog project
- Copy the Project API key (client capture)
- For the Analytics dashboard (
/dashboard/analytics), also create a Personal API key with Query Read - Set env vars:
| Variable | Scope | Purpose |
|---|---|---|
NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN | Client | Event capture |
NEXT_PUBLIC_POSTHOG_HOST | Client | Ingest host (US/EU) |
POSTHOG_PERSONAL_API_KEY | Server | HogQL queries |
POSTHOG_PROJECT_ID | Server | Project ID for queries |
POSTHOG_HOST | Server | API host for queries (not ingest) |
Without the project token, analytics is disabled — app works normally.
Client vs server tracking
| Layer | Module | Use for |
|---|---|---|
| Client | src/lib/analytics/client.ts | Browser events (sign-in, sign-up) |
| Server | src/lib/analytics/server.ts | Server actions, webhooks (links, files, billing) |
Client init: src/instrumentation-client.ts. Server uses a module singleton — fail-open, never throws.
Events
Event names live in src/lib/analytics/events.ts:
export const ANALYTICS_EVENTS = {
userSignedUp: "user_signed_up",
linkCreated: "link_created",
fileUploaded: "file_uploaded",
checkoutStarted: "checkout_started",
// ...
} as const;Convention: {object}_{past_tense_verb} (lowercase, underscores).
Add a custom event
- Add the event name to
ANALYTICS_EVENTSinevents.ts - Add typed properties to
AnalyticsEventProperties(optional) - Capture from the right layer:
// Client component
import { captureClientEvent } from "@/lib/analytics/client";
captureClientEvent(ANALYTICS_EVENTS.linkCreated, { link_id, slug, destination_host });
// Server action
import { captureServerEvent } from "@/lib/analytics/server";
captureServerEvent({ distinctId: userId, event: ANALYTICS_EVENTS.linkCreated, properties: { ... } });Properties are scrubbed before send (src/lib/analytics/scrub.ts) — no passwords, tokens, or raw URLs with secrets.
Analytics dashboard
/dashboard/analytics runs HogQL queries via src/lib/analytics/query.ts. Requires POSTHOG_PERSONAL_API_KEY + POSTHOG_PROJECT_ID. Results are cached ~60s per user.
Where to change this
| What | Where |
|---|---|
| Event taxonomy | src/lib/analytics/events.ts |
| Client capture | src/lib/analytics/client.ts |
| Server capture | src/lib/analytics/server.ts |
| Config & enable checks | src/lib/analytics/config.ts |
| Dashboard queries | src/lib/analytics/query.ts |
| Analytics UI | src/features/analytics/ |
Environment Variables — all PostHog env vars.