Skip to content

Conversation

@wizard-ci-bot
Copy link

@wizard-ci-bot wizard-ci-bot bot commented Jan 21, 2026

Automated wizard CI run

Source: manual
Trigger ID: bd5a2b4
App: react-router/saas-template
App directory: apps/react-router/saas-template
Workbench branch: wizard-ci-bd5a2b4-react-router-saas-template
Wizard branch: main
Examples branch: main
PostHog (MCP) branch: master
Timestamp: 2026-01-21T21:12:25.107Z
Duration: 650.0s

@wizard-ci-bot
Copy link
Author

wizard-ci-bot bot commented Jan 21, 2026

Now I have enough context to provide a comprehensive evaluation. Let me compile my review:


PR Evaluation Report

Summary

This PR integrates PostHog analytics into a React Router 7 SaaS template application. It adds both client-side (posthog-js, @posthog/react) and server-side (posthog-node) SDKs, implements a middleware for server-side event tracking with session linking, captures 15 distinct business events across authentication, onboarding, billing, and organization flows, and includes error boundary exception capture.

Files changed Lines added Lines removed
26 +982 -148

Confidence score: 3/5 🤔

  • Missing user identification: No posthog.identify() calls to associate events with user IDs - server events use customer/organization IDs as distinctId, but client-side lacks user identification [CRITICAL]
  • Missing automatic pageview tracking: Client-side PostHog initialization does not enable capture_pageview or use page leave capture, meaning pageview tracking is not set up [MEDIUM]
  • No reverse proxy configured: No reverse proxy setup to circumvent ad blockers when sending events to PostHog [MEDIUM]
  • Client-side tracing headers config: The __add_tracing_headers option uses [window.location.host, "localhost"] but the headers are not being attached to server requests - the middleware reads X-POSTHOG-SESSION-ID and X-POSTHOG-DISTINCT-ID headers but the client never sends them [CRITICAL]

File changes

Filename Score Description
.env.example 5/5 Correctly adds VITE_PUBLIC_POSTHOG_KEY and VITE_PUBLIC_POSTHOG_HOST environment variables
app/entry.client.tsx 3/5 Initializes PostHog with defaults: "2025-11-30" and wraps app in PostHogProvider, but __add_tracing_headers doesn't automatically send headers to server
app/lib/posthog/posthog-middleware.server.ts 3/5 Creates PostHog server client with context, but reads headers that client never sends; creates new client per request which is appropriate
app/root.tsx 4/5 Correctly adds middleware and captures exceptions in ErrorBoundary via captureException
vite.config.ts 5/5 Properly configures ssr.noExternal for PostHog packages
package.json 5/5 Adds all required dependencies: posthog-js, posthog-node, @posthog/react
app/features/billing/billing-action.server.ts 4/5 Captures 4 billing events with relevant properties; captures at intent-start not completion for some events
app/features/billing/stripe-event-handlers.server.ts 4/5 Creates standalone PostHog clients for webhook handlers with proper shutdown; good pattern for webhooks
app/features/billing/contact-sales/contact-sales-action.server.ts 4/5 Captures contact sales submission with company name
app/features/user-authentication/login/login-action.server.ts 4/5 Captures login events with method property
app/features/user-authentication/registration/register-action.server.ts 4/5 Captures signup events with method property
app/features/onboarding/*/ 4/5 Captures onboarding completion events with appropriate properties
app/features/organizations/*/ 4/5 Captures organization creation and invite acceptance events
Other refactored files 5/5 Code formatting changes (Infinity→Number.POSITIVE_INFINITY, import ordering) are appropriate

App sanity check: 4/5 ✅

Criteria Result Description
App builds and runs Yes Dependencies are properly added, imports are correct, no syntax errors detected
Preserves existing env vars & configs Yes Existing env vars preserved, new PostHog vars added appropriately
No syntax or type errors Yes TypeScript types properly handled with PostHogContext interface
Correct imports/exports Yes All imports/exports are correct, middleware properly exported
Minimal, focused changes Yes Changes are focused on PostHog integration; code reformatting is minor

Issues

  • Code reformatting mixed with feature changes: Several files have code reformatting (property ordering, import sorting) mixed with PostHog changes, making review harder but not affecting functionality [LOW]

Other completed criteria

  • Environment variables documented in .env.example
  • Build configuration properly updated in vite.config.ts
  • No hardcoded API keys
  • Proper TypeScript types defined for context

PostHog implementation: 3/5 ⚠️

Criteria Result Description
PostHog SDKs installed Yes posthog-js, posthog-node, and @posthog/react added to package.json
PostHog client initialized Yes Client initialized in entry.client.tsx with provider; server middleware creates per-request clients
capture() Yes 15 distinct events captured across server actions
identify() No No posthog.identify() calls anywhere - users are not properly identified
Error tracking Yes captureException() called in root ErrorBoundary
Reverse proxy No No reverse proxy configuration to circumvent ad blockers

Issues

  • Missing user identification: No posthog.identify() calls to associate anonymous visitors with authenticated user IDs. When users log in or sign up, their identity should be established. [CRITICAL]
  • Client-server session linking not working: The middleware expects X-POSTHOG-SESSION-ID and X-POSTHOG-DISTINCT-ID headers, but __add_tracing_headers only adds tracing headers to fetch requests made via PostHog's network capture, not all server requests. Server actions won't receive these headers. [CRITICAL]
  • No pageview tracking: capture_pageview is not enabled in initialization. Default pageview capture is disabled. [MEDIUM]
  • No reverse proxy: Events may be blocked by ad blockers without a reverse proxy [MEDIUM]

Other completed criteria

  • API key via environment variable (not hardcoded)
  • Correct API host configuration
  • PostHogProvider wrapping the app
  • Proper cleanup with posthog.shutdown() in server handlers
  • Webhook handlers create isolated PostHog clients (good pattern)

PostHog insights and events: 4/5 ✅

Filename PostHog events Description
register-action.server.ts user signed up Captures registration with signup_method (email/google)
login-action.server.ts user logged in Captures login with login_method (email/google)
onboarding-user-account-action.server.ts onboarding user account completed Tracks user profile completion
onboarding-organization-action.server.ts onboarding organization completed Tracks org setup with org_id and name
create-organization-action.server.ts organization created Tracks new organization creation
accept-email-invite-action.server.ts email invite accepted Tracks team growth via email invites
accept-invite-link-action.server.ts invite link accepted Tracks team growth via invite links
billing-action.server.ts subscription cancelled, checkout started, subscription resumed, subscription plan switched Comprehensive billing funnel tracking
contact-sales-action.server.ts contact sales submitted Enterprise lead capture
stripe-event-handlers.server.ts checkout completed, subscription created, subscription deleted Server-side Stripe webhook events
root.tsx captureException Error tracking in ErrorBoundary

Issues

  • Events captured before action completes: Some events like "subscription cancelled" are captured when user initiates cancellation, not when it succeeds. This could track failed attempts. [MEDIUM]
  • Missing user context on server events: Without proper session linking, server events won't be associated with the user's client session [MEDIUM]

Other completed criteria

  • Events represent real user actions and product flows
  • Events cover full user lifecycle (signup → onboarding → usage → billing)
  • Billing events enable revenue/churn analysis
  • Events enriched with relevant properties (organization_id, login_method, etc.)
  • Error tracking captures exceptions for debugging

Reviewed by wizard workbench PR evaluator

@wizard-ci-bot wizard-ci-bot bot added the CI/CD label Jan 21, 2026
@wizard-ci-bot wizard-ci-bot bot closed this Jan 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant