Skip to content

Conversation

@wizard-ci-bot
Copy link

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

Automated wizard CI run

Source: manual
Trigger ID: afd8cc2
App: next-js/15-app-router-saas
App directory: apps/next-js/15-app-router-saas
Workbench branch: wizard-ci-afd8cc2-next-js-15-app-router-saas
Wizard branch: main
Examples branch: main
PostHog (MCP) branch: master
Timestamp: 2026-01-16T14:00:44.601Z
Duration: 383.1s

@wizard-ci-bot
Copy link
Author

wizard-ci-bot bot commented Jan 16, 2026

Now I have all the information needed to provide a comprehensive evaluation. Let me compile the PR review.


PR Evaluation Report

Summary

This PR integrates PostHog analytics into a Next.js 15 SaaS application with both client-side and server-side tracking. The implementation includes user authentication events, subscription lifecycle tracking, team management events, and a reverse proxy for ad-blocker circumvention. The integration follows modern Next.js patterns using instrumentation-client.ts for initialization.

Files changed Lines added Lines removed
14 +624 -10

Confidence score: 4/5 👍

  • PII in events: Email is passed as a property in user_signed_in and user_signed_up events (line 41 in login.tsx). While identifying by email is acceptable, sending email as an event property is redundant and borderline PII exposure. [MEDIUM]
  • Server-side distinctId inconsistency: Webhook uses subscription.customer (Stripe customer ID) while checkout uses user[0].email. This creates inconsistent user identification across server-side events, making it harder to correlate events in PostHog. [MEDIUM]
  • No posthog.shutdown() call in server routes: Server-side PostHog client is never explicitly flushed/shutdown after capturing events, which could lead to events being lost in serverless environments. [MEDIUM]

File changes

Filename Score Description
app/(dashboard)/dashboard/general/page.tsx 4/5 Adds account_updated event tracking using useEffect with pending state transition pattern
app/(dashboard)/dashboard/page.tsx 4/5 Adds manage_subscription_clicked, team_member_removed, and team_member_invited events with subscription context properties
app/(dashboard)/dashboard/security/page.tsx 4/5 Adds password_updated and account_deleted events with proper posthog.reset() on account deletion
app/(dashboard)/layout.tsx 5/5 Adds user_signed_out event with posthog.reset() before sign out - clean implementation
app/(dashboard)/pricing/submit-button.tsx 4/5 Adds checkout_started event on button click
app/(login)/login.tsx 3/5 Adds user_signed_in/user_signed_up events with posthog.identify(). Contains PII (email) in event properties
app/api/stripe/checkout/route.ts 3/5 Server-side checkout_completed tracking with good properties. Uses email as distinctId. Includes exception capture but no explicit flush
app/api/stripe/webhook/route.ts 3/5 Server-side subscription_updated/subscription_cancelled events using Stripe customer ID as distinctId (inconsistent with checkout)
instrumentation-client.ts 4/5 Clean PostHog initialization using Next.js 15.3+ pattern with reverse proxy, exception capture, and debug mode
lib/posthog-server.ts 3/5 Singleton pattern for server-side PostHog. Uses flushAt: 1, flushInterval: 0 which is aggressive but may be needed for serverless. No shutdown integration
next.config.ts 5/5 Proper reverse proxy rewrites for PostHog with skipTrailingSlashRedirect
package.json 5/5 Correctly adds posthog-js and posthog-node dependencies
pnpm-lock.yaml 5/5 Lock file updated with PostHog dependencies
posthog-setup-report.md 4/5 Comprehensive documentation of implemented events and next steps

App sanity check: 4/5 ✅

Criteria Result Description
App builds and runs Yes Dependencies added correctly, no breaking changes to existing logic
Preserves existing env vars & configs Yes Only adds PostHog-related config, existing app config preserved
No syntax or type errors Yes TypeScript types are correct, imports are valid
Correct imports/exports Yes All PostHog imports use correct package names (posthog-js for client, posthog-node for server)
Minimal, focused changes Yes Changes are strictly PostHog-related, no unnecessary modifications

Issues

  • Environment variables not documented in code: The NEXT_PUBLIC_POSTHOG_KEY and NEXT_PUBLIC_POSTHOG_HOST are required but there's no .env.example or runtime validation to catch missing values. [LOW]

Other completed criteria

  • Existing app logic (forms, actions, routing) unchanged
  • React patterns preserved (Suspense boundaries, SWR data fetching)
  • Error handling maintained in original code
  • Build configuration valid with proper TypeScript config

PostHog implementation: 4/5 ✅

Criteria Result Description
PostHog SDKs installed Yes posthog-js@^1.325.0 and posthog-node@^5.21.0 added to dependencies
PostHog client initialized Yes Client initialized in instrumentation-client.ts with reverse proxy api_host (/ingest), exception capture enabled
capture() Yes 12 distinct events captured across client and server components
identify() Yes User identified with email on sign-in/sign-up in login.tsx
Error tracking Yes capture_exceptions: true enabled in client config, captureException() used in checkout error handling
Reverse proxy Yes Properly configured in next.config.ts with rewrites to us.i.posthog.com and us-assets.i.posthog.com

Issues

  • Server-side distinctId inconsistency: Checkout uses user[0].email as distinctId, but webhook uses subscription.customer (Stripe customer ID). This breaks user correlation in PostHog. Should consistently use email or a stable user identifier. [MEDIUM]
  • No server-side flush/shutdown: Events captured server-side may be lost in serverless environments without explicit posthog.shutdown() call after capturing. Consider using await posthog.shutdown() at end of API routes. [MEDIUM]
  • PII in event properties: Email is passed in event properties for sign-in/sign-up events. This is redundant since user is already identified. [LOW]

Other completed criteria

  • posthog.reset() called on sign-out and account deletion
  • Debug mode enabled only in development
  • Modern instrumentation-client.ts pattern used (Next.js 15.3+)
  • skipTrailingSlashRedirect: true configured for PostHog compatibility
  • defaults: '2025-05-24' configuration string used for latest defaults

PostHog insights and events: 4/5 ✅

Filename PostHog events Description
login.tsx user_signed_in, user_signed_up Authentication funnel tracking with user identification
layout.tsx user_signed_out Session end tracking with proper reset
submit-button.tsx checkout_started Conversion funnel entry point
checkout/route.ts checkout_completed, capturedException Server-side conversion completion with rich subscription properties
webhook/route.ts subscription_updated, subscription_cancelled Server-side subscription lifecycle tracking
general/page.tsx account_updated Account settings engagement
security/page.tsx password_updated, account_deleted Security-related user actions
dashboard/page.tsx team_member_invited, team_member_removed, manage_subscription_clicked Team management and subscription portal engagement

Issues

  • Missing pageview tracking: No explicit pageview events configured. While PostHog auto-captures pageviews by default, this should be verified works with the reverse proxy setup. [LOW]
  • Limited event properties: Some events like account_updated, password_updated, team_member_removed, team_member_invited capture no properties. Adding context (e.g., role for team events) would improve insights. [LOW]

Other completed criteria

  • Full user journey tracked: signup → checkout → subscription management → account actions
  • Subscription events include rich properties (plan_name, subscription_id, customer_id, status)
  • Manage subscription click includes current plan and status context
  • Events are snake_case and follow consistent naming convention
  • Documentation includes suggested PostHog dashboard insights

Reviewed by wizard workbench PR evaluator

@wizard-ci-bot wizard-ci-bot bot added the CI/CD label Jan 16, 2026
@wizard-ci-bot wizard-ci-bot bot closed this Jan 16, 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