Product Analytics and Feature Flags
Status note
This document is the canonical first-pass direction for product analytics, feature flags, and lightweight experimentation in VRDex.
Use it when deciding whether a feature should ship directly, behind a flag, with staged rollout, or with explicit product instrumentation.
Locked decision
- product analytics and feature flags are part of delivery discipline, not bolt-ons after launch
- the repo should prefer one primary tool per concern until a real gap appears
Langfuseis not a substitute for product analytics or feature flags; it is a separate LLM and agent observability concern- trivial or obviously low-risk work should not be forced through heavyweight instrumentation or rollout ceremony
Current recommendation
- use
PostHogas the first-pass default for product analytics, feature flags, and basic experiments - defer
Google Analyticsunless there is a concrete marketing or top-of-funnel website need thatPostHogis not covering well enough - defer
LaunchDarklyor another dedicated flag platform unless rollout sophistication clearly outgrows the integrated approach - require non-trivial feature issues to state rollout posture and success-signal expectations explicitly, even when the answer is
not needed
Why this is the current recommendation
PostHogcovers the main early needs in one place: product events, feature flags, and simple experiments- an integrated tool keeps setup and contributor expectations simpler during v0.5 and early v1
- separate tools can still be added later if scale, governance, or rollout complexity justifies the extra operational drag
Tool roles
PostHog
Use as the default first-pass system for:
- product analytics
- feature flags and kill switches
- lightweight experiments
- launch and adoption signals for new features
Google Analytics
Treat as optional later infrastructure for:
- marketing-site traffic
- acquisition and SEO reporting
- top-of-funnel website analysis if a real gap appears
Do not treat it as the main product analytics backbone by default.
LaunchDarkly
Treat as a credible later option if VRDex needs:
- more advanced rollout governance
- stronger environment separation or approval controls
- flag management that has clearly outgrown the integrated default
Do not add it just because it is a well-known flag vendor.
Langfuse
Treat as a separate concern for:
- LLM and agent traces
- evals and prompt-quality analysis
- agent loop health and observability
It does not replace product instrumentation.
Minimum expectation for v0.5 non-trivial features
Before implementation starts, every non-trivial feature should answer:
- What is the rollout posture: direct ship, flagged, or staged?
- Is a feature flag or kill switch needed?
- What is the primary success signal?
- Is any guardrail or health signal needed?
- If instrumentation is deferred, what simpler signal or follow-up issue covers the gap?
This should stay lightweight. The point is to avoid shipping blind, not to build a miniature BI program for every issue.
When direct ship is usually acceptable
- typo, copy, and docs-only changes
- low-risk bug fixes with narrow blast radius
- internal cleanup or refactors with no user-visible behavior change
- small admin or operator improvements where staged rollout adds little value
When feature flags are usually expected
- new user-facing flows where adoption or UX is uncertain
- claim, identity, permissions, trust, moderation, or billing-adjacent changes
- features with meaningful blast radius or rollback risk
- work that benefits from fast disablement without a redeploy
When explicit analytics are usually expected
- onboarding or activation changes
- discovery, profile, community, or event flows where usage matters to product learning
- paid conversion, premium unlock, or other monetization-adjacent changes
- experiments where success should be measured instead of guessed
Lightweight acceptable answers
Not needed is acceptable when it is honest and brief.
Examples:
Rollout: not needed - narrow bug fix with low blast radiusSignals: not needed - success is binary and covered by manual verificationGuardrail: not needed - no meaningful user-facing behavior change
Agent-first workflow expectations
docs/agentic/definition-of-ready.mdshould reference this policy when asking for rollout and signal plansdocs/agentic/definition-of-done.mdshould reference this policy when checking rollout state and instrumentation completion- if a feature intentionally launches without desired instrumentation, record that explicitly and create follow-up work when needed
- do not let agents hide behind
future analyticslanguage without saying what the temporary success signal is
Candidate direction
- standardize a small event taxonomy once the app implementation starts, likely around activation, discovery, conversion, and trust-critical flows
- add a reusable implementation helper layer so contributors do not hand-roll flag or event calls inconsistently
- define environment defaults such as local-dev behavior, preview behavior, and production-safe fallbacks once the app exists
First Discovery Event Taxonomy
Current discovery instrumentation uses PostHog when NEXT_PUBLIC_POSTHOG_KEY is configured and otherwise no-ops safely.
Locked hosted project:
- organization:
BASIC BIT LLC - project:
VRDex Analytics - project ID:
447783 - app host:
https://us.posthog.com/project/447783/home - ingestion host:
https://us.i.posthog.com
The hosted PostHog project is managed/imported through infra/terraform/posthog. Hosted Vercel env vars for this project are managed by infra/terraform/vercel. Keep the public project key out of committed defaults so forks and self-hosted installs do not accidentally send analytics into the BASIC BIT project.
Implemented rollout foundation
Locked implementation behavior:
- Convex authorization remains the source of truth for private data. A PostHog person property, cohort, or feature flag must never grant backend access.
- The
seed-lookup-betaflag targets the string person propertyseed_lookup_beta=true. The web app mirrors an already-authorized Convex result into that property and does not send a raw account identifier. - The
featured-discoveryflag is disabled by default. It controls the unfinished Featured module on/discoveryuntil editorial, recommendation, and paid-placement behavior has a reviewed policy. - The Terraform provider manages the feature flag directly. Its current schema does not manage cohorts, so an optional analytic cohort may be derived from the same property in PostHog without becoming an authorization dependency.
- Browser events use the same-origin
/ingestreverse proxy. Next.js routes ingestion and SDK asset requests to the configured PostHog host. - Session replay runs on every route (BASIC's decision, 2026-07-27), superseding
the earlier public-route allowlist. Safety comes from masking rather than
route exclusion: every private route group carries a blocking layout, and
tests/web/session-replay-routes.test.tsfails if a route group ships without being classified as private-with-a-layout or explicitly public. - PostHog's
ph-no-captureclass excludes marked private surfaces from autocapture, while[data-ph-no-capture]blocks and masks session replay. - Inputs are masked,
[data-ph-no-capture]blocks sensitive surfaces, URL queries and fragments are removed, and/handoff/<token>is normalized to/handoff/redactedbefore capture.
The proxy adds application-host transfer and request volume. Recording every route raises both, which the blocking layouts bound on the privacy side: a blocked route still produces a session, but its DOM is not captured.
Initial events:
search_submittedsearch_result_clickeddiscovery_filter_selectedevent_card_clickedfeatured_card_clickedlookup_submittedprivate_seed_results_shown
Authentication lifecycle events are intentionally separate from product identity and content:
auth_session_restore_completedauth_session_restore_slowauth_session_signout_requestedauth_session_state_changedrecent_auth_challenge_presentedrecent_auth_challenge_completedsensitive_action_deniedsession_revocation_requestedsession_revocation_startedsession_revocation_completedsession_revocation_detected
Application-supplied properties use fixed deployment, browser/OS family,
route-class, latency, transition-intent, action-class, outcome, and revocation
scope enums only. Do not attach tokens, IDs, emails, provider payloads,
redirects, route slugs, IP addresses, or device fingerprints. PostHog's SDK
still supplies its standard transport envelope and person/session metadata;
this narrower contract applies to properties supplied by VRDex. Authentication,
account, claim, and developer routes are recorded like every other route, with
their DOM blocked from capture by a route-level [data-ph-no-capture] layout.
Discovery and lookup events avoid search terms, profile slugs, private profile fields, raw authentication identifiers, seed values, and unsupported popularity claims. Revisit retention and privacy copy before broad public launch.
Product-learning data
Locked decision:
- Product analytics events should remain sparse and avoid raw user content.
- A product workflow may separately retain user-submitted source material when that material is genuinely useful for improving the product, the purpose is disclosed, and the user can opt out.
- PostHog is not the raw-content store. Retained source material belongs in a controlled product record with owner, purpose, retention state, deletion support, and access boundaries.
- VRDex does not sell retained user-submitted source material.
The temporal parser is the first explicit application of this rule. It may retain temporal input text for parser improvement unless the account or request opts out. The UI and API must warn users not to submit sensitive material. Raw temporal text must not appear in PostHog properties, URLs, session replay, ordinary logs, or provider telemetry. This narrow decision does not authorize unannounced capture in unrelated editors, private forms, claims, or imports.
Before enabling replay or raw-content learning beyond the closed beta, document the consent or other legal basis, content-retention period, staff-access boundary, deletion path, and account opt-out behavior for that exact surface.
The temporal-parsing-beta PostHog flag mirrors the backend-authorized
use_temporal_parsing_beta grant for UI rollout and measurement. Convex remains
the authorization source of truth.
Interview later
- whether public marketing pages eventually justify a separate
Google Analyticsinstallation - whether
PostHogremains sufficient once rollout governance and org complexity increase - which specific v0.5 events deserve to be mandatory rather than suggested
Relationship to other docs
docs/agentic/definition-of-ready.mduses this policy for rollout and success-signal expectationsdocs/agentic/definition-of-done.mduses this policy for rollout-state and instrumentation closeout expectationsdocs/planning/engineering-strategy.mdkeeps the high-level engineering rationaledocs/agentic/software-factory.mdplaces this policy inside the wider delivery loop