Skip to content

[CI] (7f79337) next-js/15-pages-router-saas#334

Closed
wizard-ci-bot[bot] wants to merge 1 commit intomainfrom
wizard-ci-7f79337-next-js-15-pages-router-saas
Closed

[CI] (7f79337) next-js/15-pages-router-saas#334
wizard-ci-bot[bot] wants to merge 1 commit intomainfrom
wizard-ci-7f79337-next-js-15-pages-router-saas

Conversation

@wizard-ci-bot
Copy link

@wizard-ci-bot wizard-ci-bot bot commented Feb 12, 2026

Automated wizard CI run

Source: context-mill-pr
Trigger ID: 7f79337
App: next-js/15-pages-router-saas
App directory: apps/next-js/15-pages-router-saas
Workbench branch: wizard-ci-7f79337-next-js-15-pages-router-saas
Wizard branch: main
Context Mill branch: clarify-next-provider
PostHog (MCP) branch: master
Timestamp: 2026-02-12T21:07:20.471Z
Duration: 808.7s

@wizard-ci-bot
Copy link
Author

wizard-ci-bot bot commented Feb 12, 2026


PR Evaluation Report

Summary

This PR integrates PostHog analytics into a Next.js 15 Pages Router SaaS application. It adds both client-side (posthog-js) and server-side (posthog-node) tracking with comprehensive event capture across authentication, Stripe payment flows, team management, and account updates. The integration includes proper reverse proxy configuration and error tracking.

Files changed Lines added Lines removed
20 +731 -7

Confidence score: 3/5 🤔

  • Duplicate/redundant events: Both client-side and server-side events fire for the same user actions (e.g., user_logged_in on client and user_signed_in on server). This creates duplicate data and may confuse analytics. [MEDIUM]
  • User identification uses email as distinct ID on client: The client-side posthog.identify(data.email, {...}) uses email as the distinct ID, while server-side uses numeric user ID. This will create identity resolution issues in PostHog. [CRITICAL]
  • PII in event properties: Email addresses are included in event properties across multiple events, which may violate privacy requirements. [MEDIUM]
  • Webhook events use Stripe customer ID as distinct ID: For subscription events, the Stripe customer ID is used instead of the user ID, making it difficult to correlate with user analytics. [MEDIUM]
  • instrumentation-client.ts uses unsupported defaults option: The defaults: '2026-01-30' config option is not a recognized PostHog SDK option and may cause issues. [MEDIUM]

File changes

Filename Score Description
instrumentation-client.ts 3/5 Client-side PostHog init with error tracking; uses unrecognized defaults option
lib/posthog-server.ts 4/5 Clean server singleton pattern with immediate flush settings
next.config.ts 5/5 Correct reverse proxy rewrites for PostHog
package.json 5/5 Added both posthog-js and posthog-node dependencies
components/header.tsx 4/5 Logout tracking with proper posthog.reset()
components/login.tsx 2/5 Identifies user by email instead of user ID; creates identity mismatch
pages/api/auth/sign-in.ts 4/5 Server-side signin event with proper user ID
pages/api/auth/sign-out.ts 4/5 Server-side signout with user ID
pages/api/auth/sign-up.ts 4/5 Server-side signup with user ID and properties
pages/api/stripe/checkout.ts 4/5 Checkout completion tracking
pages/api/stripe/create-checkout.ts 4/5 Checkout started tracking
pages/api/stripe/customer-portal.ts 4/5 Portal access tracking
pages/api/stripe/webhook.ts 3/5 Uses Stripe customer ID instead of user ID for distinct_id
pages/api/team/invite.ts 4/5 Team invite tracking
pages/api/team/remove-member.ts 4/5 Team member removal tracking
pages/api/account/update.ts 4/5 Account update with identify() call
pages/pricing.tsx 4/5 Pricing plan click tracking
.gitignore 5/5 Correctly ignores .env.local
pnpm-lock.yaml 5/5 Lock file updated correctly
posthog-setup-report.md 3/5 Documentation included but contains truncated API key

App sanity check: 4/5 ✅

Criteria Result Description
App builds and runs Yes Dependencies added correctly, TypeScript types should resolve
Preserves existing env vars & configs Yes Only adds PostHog-related config, preserves existing Next.js config
No syntax or type errors Yes All TypeScript code follows proper patterns
Correct imports/exports Yes All imports are valid and consistent
Minimal, focused changes Yes Changes are focused on PostHog integration only

Issues

  • defaults config option: The defaults: '2026-01-30' in instrumentation-client.ts is not a valid PostHog SDK option and should be removed. [MEDIUM]

Other completed criteria

  • Existing app logic preserved in all modified files
  • Error handling patterns maintained
  • No breaking changes to existing functionality
  • Environment variables documented in setup report

PostHog implementation: 3/5 ⚠️

Criteria Result Description
PostHog SDKs installed Yes posthog-js@^1.347.0 and posthog-node@^5.24.15 in package.json
PostHog client initialized Yes Client via instrumentation-client.ts, server via singleton in lib/posthog-server.ts
capture() Yes Extensive event capture across auth, payments, teams
identify() Partial Server-side uses user ID, client-side incorrectly uses email
Error tracking Yes captureException() used in all error handlers; capture_exceptions: true enabled
Reverse proxy Yes Correct rewrites in next.config.ts with skipTrailingSlashRedirect

Issues

  • Identity mismatch between client and server: Client-side posthog.identify(data.email, {...}) in login.tsx uses the user's email as the distinct ID, while server-side uses user.id.toString(). This will create separate user profiles in PostHog. Should use the same identifier (user ID) on both client and server. [CRITICAL]
  • Webhook distinct_id uses Stripe customer ID: In webhook.ts, events use subscription.customer as the distinct ID instead of the actual user ID. This breaks user analytics correlation. Should look up the user from the team's Stripe customer ID. [MEDIUM]
  • Server-side PostHog client not awaited: The posthog.capture() and posthog.identify() calls are not awaited, and with flushAt: 1, flushInterval: 0, events may be lost if the function returns before flush completes. [MEDIUM]
  • Email included in event properties: Multiple events include email in properties, which is PII and should be avoided or anonymized. [LOW]

Other completed criteria

  • API key via environment variable (not hardcoded)
  • Correct US API host configuration
  • posthog.reset() called on logout
  • capture_exceptions: true for automatic error tracking
  • debug mode enabled only in development

PostHog insights and events: 4/5 ✅

Filename PostHog events Description
components/login.tsx user_logged_in, user_signed_up, captureException Tracks successful client-side auth with email property
components/header.tsx user_logged_out, captureException Tracks logout with PostHog reset for session end
pages/pricing.tsx pricing_plan_clicked, captureException Tracks pricing intent with plan details (name, price, interval)
pages/api/auth/sign-in.ts user_signed_in, identify, captureException Server-side signin with team context
pages/api/auth/sign-up.ts user_signed_up, identify, captureException Server-side signup with invite/team tracking
pages/api/auth/sign-out.ts user_signed_out Server-side signout
pages/api/stripe/create-checkout.ts checkout_started, captureException Payment funnel entry point with priceId
pages/api/stripe/checkout.ts checkout_completed, captureException Payment success with plan, subscription, customer details
pages/api/stripe/webhook.ts subscription_updated, subscription_cancelled Stripe lifecycle events for churn analysis
pages/api/stripe/customer-portal.ts customer_portal_accessed, captureException Billing intent tracking
pages/api/team/invite.ts team_member_invited, captureException Team growth tracking with invited role
pages/api/team/remove-member.ts team_member_removed, captureException Team churn tracking
pages/api/account/update.ts account_updated, identify, captureException Profile update tracking with field info

Issues

  • Duplicate client/server events: Having both user_logged_in (client) and user_signed_in (server) for the same action creates confusion. Should use one source of truth. [LOW]
  • Missing page view tracking verification: While instrumentation-client.ts initializes PostHog, there's no explicit capture_pageview setting. Default behavior should work but is not verified. [LOW]

Other completed criteria

  • Events capture real user actions across full product lifecycle
  • Signup → Checkout funnel fully instrumented
  • Subscription lifecycle (update/cancel) captured from webhooks
  • Team collaboration events (invite/remove) captured
  • Properties enriched with teamId, priceId, planName, etc.
  • Exception capture throughout for error monitoring

Reviewed by wizard workbench PR evaluator

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.

0 participants