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-pages-router-saas
App directory: apps/next-js/15-pages-router-saas
Workbench branch: wizard-ci-afd8cc2-next-js-15-pages-router-saas
Wizard branch: main
Examples branch: main
PostHog (MCP) branch: master
Timestamp: 2026-01-16T14:02:06.346Z
Duration: 462.1s

@wizard-ci-bot
Copy link
Author

wizard-ci-bot bot commented Jan 16, 2026

Now I have read all the changed files. Let me compile the PR evaluation report.


PR Evaluation Report

Summary

This PR adds a comprehensive PostHog integration to a Next.js 15 Pages Router SaaS application. It includes client-side initialization via instrumentation-client.ts, server-side tracking via a singleton PostHog client, a reverse proxy for ad-blocker circumvention, and event tracking across authentication, subscription, and team management flows.

Files changed Lines added Lines removed
18 +785 -6

Confidence score: 3/5 🤔

  • Inconsistent server-side host configuration: The server client uses NEXT_PUBLIC_POSTHOG_HOST which differs from client-side that uses the /ingest proxy. This creates inconsistency and server events may not go through the proxy. [MEDIUM]
  • Missing await posthog.shutdown() calls: Server-side PostHog calls are fire-and-forget in serverless API routes. Without awaiting shutdown() or using flush patterns, events may be lost in cold starts or short-lived functions. [CRITICAL]
  • Webhook distinct_id uses Stripe customer ID instead of user email: The webhook events use subscription.customer (a Stripe customer ID) as distinctId, making it disconnected from the user's actual PostHog identity which uses email. [MEDIUM]
  • Client-side page view tracking not explicitly configured: The instrumentation-client.ts doesn't enable capture_pageview - relies on default behavior which may not track page views in Pages Router SPAs correctly. [MEDIUM]

File changes

Filename Score Description
instrumentation-client.ts 4/5 New file - client PostHog init with defaults '2025-05-24', exception capture, debug mode. Missing explicit pageview config.
lib/posthog-server.ts 3/5 New file - singleton pattern, but uses different host than client proxy. flushAt: 1 and flushInterval: 0 are aggressive but may cause issues in serverless.
next.config.ts 5/5 Correctly configured reverse proxy rewrites for /ingest to PostHog US endpoints with trailing slash support.
package.json 5/5 Added posthog-js ^1.325.0 and posthog-node ^5.21.0 dependencies correctly.
components/header.tsx 5/5 Properly tracks signed_out and calls posthog.reset() before sign-out API call.
components/login.tsx 4/5 Adds posthog.identify() on successful login and captureException on errors. Duplicated identify calls for both redirect paths.
pages/pricing.tsx 5/5 Tracks checkout_started with plan details and captureException on errors.
pages/api/auth/sign-in.ts 3/5 Tracks signed_in and identifies user server-side. Events may not flush before response returns.
pages/api/auth/sign-up.ts 3/5 Tracks signed_up with rich properties. Same flush concern as sign-in.
pages/api/stripe/checkout.ts 3/5 Tracks checkout_completed. Missing await on PostHog operations.
pages/api/stripe/create-checkout.ts 3/5 Tracks checkout_session_created. Same flush concern.
pages/api/stripe/customer-portal.ts 3/5 Tracks customer_portal_opened. Same flush concern.
pages/api/stripe/webhook.ts 2/5 Tracks subscription events but uses Stripe customerId as distinctId - breaks identity linkage.
pages/api/team/invite.ts 3/5 Tracks team_member_invited. Same flush concern.
pages/api/team/remove-member.ts 3/5 Tracks team_member_removed. Same flush concern.
pages/api/account/update.ts 3/5 Tracks account_updated and updates person properties. Same flush concern.
pnpm-lock.yaml 5/5 Lock file correctly updated with PostHog dependencies.
posthog-setup-report.md 4/5 Good documentation of events and setup, but .env file mentioned as created is not in the PR.

App sanity check: 4/5 ✅

Criteria Result Description
App builds and runs Yes No syntax errors, all imports valid, TypeScript types correct
Preserves existing env vars & configs Yes Only additive changes to next.config.ts, existing config preserved
No syntax or type errors Yes All files have correct TypeScript syntax and types
Correct imports/exports Yes All PostHog imports are correct for both JS and Node packages
Minimal, focused changes Yes Changes are focused on PostHog integration only

Issues

  • Missing .env file: The setup report mentions .env was created but it's not in the PR diff. Users need NEXT_PUBLIC_POSTHOG_KEY and NEXT_PUBLIC_POSTHOG_HOST documented. [LOW]

Other completed criteria

  • Clean code organization with dedicated server-side helper
  • Consistent import patterns across files
  • No modifications to existing business logic
  • Proper use of Next.js Pages Router patterns

PostHog implementation: 3/5 ⚠️

Criteria Result Description
PostHog SDKs installed Yes posthog-js ^1.325.0 and posthog-node ^5.21.0 in dependencies
PostHog client initialized Yes Client via instrumentation-client.ts, server via singleton in lib/posthog-server.ts
capture() Yes Multiple events captured across client and server
identify() Yes User identification on login, signup, and account update
Error tracking Yes capture_exceptions: true and captureException() calls
Reverse proxy Yes Correctly configured in next.config.ts rewrites

Issues

  • Server-side events may not flush: API routes don't await posthog.shutdown() or explicit flush. In serverless environments, events may be lost when the function terminates. Should call await posthog.shutdown() before returning responses in API routes. [CRITICAL]
  • Host mismatch between client and server: Client uses /ingest proxy, server uses NEXT_PUBLIC_POSTHOG_HOST directly. Server events bypass the proxy, potentially causing ad-blocker issues for server-initiated events viewed in same session. [MEDIUM]
  • Webhook identity disconnection: Stripe webhook uses subscription.customer (Stripe customer ID like cus_xxx) as distinctId instead of user email, making these events appear as separate users in PostHog. [MEDIUM]
  • No explicit pageview tracking: The client init doesn't set capture_pageview - default may not capture SPA navigation in Pages Router correctly. [LOW]

Other completed criteria

  • Uses latest defaults: '2025-05-24' for modern PostHog behavior
  • Debug mode enabled in development
  • posthog.reset() called on sign-out
  • Proper singleton pattern for server client to avoid multiple instances
  • flushAt: 1 and flushInterval: 0 configured for immediate flushing (good for serverless)

PostHog insights and events: 4/5 ✅

Filename PostHog events Description
components/header.tsx signed_out Tracks user logout for session analytics
components/login.tsx captureException Error tracking for login failures
pages/pricing.tsx checkout_started, captureException Tracks checkout funnel entry with plan details
pages/api/auth/sign-in.ts signed_in Auth event with team context
pages/api/auth/sign-up.ts signed_up Registration event with invite tracking
pages/api/stripe/checkout.ts checkout_completed Subscription activation with plan details
pages/api/stripe/create-checkout.ts checkout_session_created Checkout initiation server-side
pages/api/stripe/customer-portal.ts customer_portal_opened Billing management access
pages/api/stripe/webhook.ts subscription_updated, subscription_canceled Subscription lifecycle events
pages/api/team/invite.ts team_member_invited Team growth tracking
pages/api/team/remove-member.ts team_member_removed Team churn tracking
pages/api/account/update.ts account_updated Profile changes tracking

Issues

  • Webhook events disconnected from user identity: subscription_updated and subscription_canceled use Stripe customer ID as distinctId. To build proper subscription funnels, these need to be linked to user email. Consider looking up user by Stripe customer ID. [MEDIUM]

Other completed criteria

  • Events cover full user lifecycle (signup → checkout → subscription → churn)
  • Rich event properties enable segmentation (plan name, team ID, role)
  • Team collaboration events enable growth analytics
  • Invited signup tracking enables referral/viral analysis
  • Exception capture enables error correlation with user journeys

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