fix: switch to PostHogProvider per official React integration guide (#112)

- Install @posthog/react and wrap app with PostHogProvider
- Use VITE_PUBLIC_POSTHOG_KEY and VITE_PUBLIC_POSTHOG_HOST env vars
- Use defaults: '2026-01-30' for recommended settings
- Remove manual initAnalytics() call — Provider handles initialization
- Analytics module now checks posthog.__loaded for readiness

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit was merged in pull request #112.
This commit is contained in:
chihlasm
2026-03-16 19:18:31 -04:00
committed by GitHub
parent c44edc5088
commit 8178657632
4 changed files with 60 additions and 39 deletions

View File

@@ -2,29 +2,24 @@
* PostHog product analytics wrapper.
*
* Tracks key user actions to understand product usage, activation,
* and engagement. All events are lightweight discrete actions — no
* pageviews or mouse tracking.
* and engagement. All events are lightweight discrete actions.
*
* Free tier: 1M events/month (more than enough for current scale).
*
* PostHog is initialized via PostHogProvider in main.tsx.
* This module provides typed event helpers that import posthog-js directly
* (valid per PostHog docs for non-component code).
*/
import posthog from 'posthog-js'
const POSTHOG_KEY = import.meta.env.VITE_POSTHOG_KEY as string | undefined
const POSTHOG_HOST = (import.meta.env.VITE_POSTHOG_HOST as string) || 'https://us.i.posthog.com'
let initialized = false
/** Initialize PostHog. Call once on app startup. */
export function initAnalytics() {
if (initialized || !POSTHOG_KEY) return
posthog.init(POSTHOG_KEY, {
api_host: POSTHOG_HOST,
autocapture: false, // We track events explicitly — no auto-capture
capture_pageview: false, // SPA — we'll track meaningful navigations, not every route
capture_pageleave: false,
persistence: 'localStorage',
})
initialized = true
/** Check if PostHog has been initialized (by the Provider). */
function isReady(): boolean {
try {
// posthog-js sets __loaded when init completes
return !!(posthog as unknown as { __loaded?: boolean }).__loaded
} catch {
return false
}
}
/** Identify a logged-in user. Call after login/fetchUser. */
@@ -35,7 +30,7 @@ export function identifyUser(user: {
is_super_admin?: boolean
account_id?: string
}) {
if (!initialized) return
if (!isReady()) return
posthog.identify(user.id, {
email: user.email,
role: user.role,
@@ -48,7 +43,7 @@ export function identifyUser(user: {
/** Reset identity on logout. */
export function resetAnalytics() {
if (!initialized) return
if (!isReady()) return
posthog.reset()
}
@@ -56,7 +51,7 @@ export function resetAnalytics() {
/** Track a named event with optional properties. */
function track(event: string, properties?: Record<string, unknown>) {
if (!initialized) return
if (!isReady()) return
posthog.capture(event, properties)
}