Documentation navigation

PostHog Funnel Analytics

Goal

Track core funnel behavior reliably in PostHog:

  1. page view
  2. signup/auth
  3. project create

Configuration

Required env vars:

  • POSTHOG_API_KEY — PostHog project API key (phc_...) for capture
  • POSTHOG_HOST — ingest host (https://us.i.posthog.com or https://eu.i.posthog.com)
  • POSTHOG_ENABLED — must be enabled for capture; a valid project key alone is not sufficient

Djass wires both frontend and backend capture through these settings. No PostHog secret is hardcoded in source.

Event mapping

Funnel Step Event Name Where Emitted Key Properties
Page view $pageview Explicit navigation capture in frontend/src/js/analytics.js, loaded through the shared template component; SDK capture_pageview: false sanitized $current_url and $pathname, plus bounded capture metadata
Signup user_signed_up apps/pages/views.py (SignupTrackingMixin._track_signup) signup_method, funnel_step=signup_completed
Auth/login user_authenticated apps/core/signals.py (track_user_login) auth_method, funnel_step=auth_completed, entrypoint=ui
Auth failure user_auth_failed apps/core/signals.py (track_user_login_failed), apps/api/views.py (create_project_v1 insufficient scope) reason, auth_method (UI only), funnel_step=auth_failed, entrypoint
Project create project_created apps/core/views.py (create_project), apps/api/views.py (create_project_v1) project_id, funnel_step=project_created, entrypoint
Project create fail project_create_failed apps/core/views.py (validation), apps/api/views.py (quota, slug, queue/internal failures) reason, optional validation_fields, optional error_type, funnel_step=project_create_failed, entrypoint

Browser page views run once on initialization and when the normalized path changes through supported HTMX history events or popstate. Query strings and fragments are removed from captured URLs; account paths and selected private identifiers are normalized. This is not a claim that every path is public-safe.

Server properties pass through the allowlist in djass/analytics.py before capture. In particular, project_name, project_slug, and required_scope are not sent by that boundary even when a producer supplies them. The table describes the retained properties, not every argument passed to a tracking task.

Source rechecked September 27, 2026. This mapping does not establish production delivery, consent compliance, or an attributed conversion rate.

Verification checklist

  1. Start app with POSTHOG_ENABLED enabled and valid POSTHOG_API_KEY + POSTHOG_HOST.
  2. Complete one test funnel flow in local or staging:
  3. open landing/home (page view)
  4. sign up or log in
  5. create a project
  6. In PostHog UI, filter recent events by your test user distinct_id and confirm all expected event names appear.

Local validation evidence (automated)

Run targeted tests:

pytest apps/pages/tests.py apps/core/tests/test_projects.py apps/core/tests/test_signals.py \
  apps/api/test_project_endpoints.py apps/api/test_api_key_authorization.py

These tests assert event names/properties for signup, auth success/failure, and project creation success/failure (UI + API).

Known gaps

  • API requests that fail before principal resolution (missing/invalid API key) cannot be attributed to a user profile_id, so they are audited in ProjectAPIAuditLog but are not emitted as PostHog user events.

Verification evidence (2026-03-11)

PostHog project djass (id=339080) was validated via API by emitting test funnel events and then reading event definitions.

Observed last_seen_at values:

  • user_signed_up — 2026-03-11T14:17:31.782029Z
  • user_authenticated — 2026-03-11T14:17:34.027492Z
  • project_created — 2026-03-11T14:17:31.782029Z