Skip to content

[CI] (dabf817) next-js/15-pages-router-saas#148

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

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

Conversation

@wizard-ci-bot
Copy link

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

Automated wizard CI run

Trigger ID: dabf817
App: next-js/15-pages-router-saas
App directory: apps/next-js/15-pages-router-saas
Workbench branch: wizard-ci-dabf817-next-js-15-pages-router-saas
Wizard branch: feat-skill-based-integration
Examples branch: rearchitect-generator
PostHog (MCP) branch: feat-mcp-skill-deployment
Timestamp: 2026-01-14T20:57:12.999Z
Duration: 408.7s

@wizard-ci-bot
Copy link
Author

wizard-ci-bot bot commented Jan 14, 2026

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


PR Evaluation Report

Summary

This PR integrates PostHog analytics into a Next.js 15 Pages Router SaaS application. It adds both client-side and server-side PostHog SDKs, configures a reverse proxy for ad-blocker resilience, implements user identification and session management, and tracks key SaaS events across authentication, subscription, and team management flows.

Files changed Lines added Lines removed
14 +572 -6

Confidence score: 3/5 🤔

  • PII Exposure in Events: Email addresses are captured in multiple events (user_signed_in, user_signed_up, team_member_invited). While email is used for identification, capturing it in event properties may violate privacy policies or GDPR requirements. [MEDIUM]
  • Server-side events never flushed: The posthog-node client in API routes (checkout.ts, webhook.ts) captures events but never calls flush() or shutdown(). In serverless environments, events may be lost before the function terminates. [CRITICAL]
  • Webhook uses Stripe customer ID as distinctId: The subscription_updated event in webhook.ts uses the Stripe customer ID as distinctId, which won't correlate with client-side events using email as the identifier. [MEDIUM]
  • pricing_viewed fires on every render: The useEffect in pricing.tsx has [products] as a dependency, which could fire multiple times if products change, and will fire on every navigation to the page regardless of user intent. [LOW]

File changes

Filename Score Description
.env.example 5/5 Properly documents PostHog environment variables with helpful comments and link to settings
components/header.tsx 4/5 Correctly captures sign-out event and resets PostHog session; clean integration
components/login.tsx 3/5 Implements identify and capture on auth, but captures email in event properties (PII concern)
instrumentation-client.ts 4/5 Modern Next.js 15.3+ initialization approach with proper config; uses defaults option correctly
lib/posthog-server.ts 3/5 Singleton pattern is good, but flushAt: 1 and flushInterval: 0 without explicit flush calls may cause issues
next.config.ts 5/5 Correct reverse proxy configuration with both static assets and API routes; includes trailing slash support
package.json 5/5 Adds both posthog-js and posthog-node with appropriate recent versions
pages/api/stripe/checkout.ts 3/5 Captures checkout completion server-side but missing flush; uses email for distinctId (consistent with client)
pages/api/stripe/webhook.ts 2/5 Uses Stripe customer ID as distinctId which breaks user correlation; missing flush call
pages/dashboard/general.tsx 4/5 Clean account_updated event capture with relevant properties
pages/dashboard/index.tsx 4/5 Good coverage of team and subscription events; captures meaningful context
pages/pricing.tsx 4/5 Good funnel tracking with pricing_viewed and checkout_started; minor useEffect concern
pnpm-lock.yaml 5/5 Lock file properly updated with PostHog dependencies and their transitive deps
posthog-setup-report.md 5/5 Comprehensive documentation of the integration with recommended insights

App sanity check: 4/5 ✅

Criteria Result Description
App builds and runs Yes No syntax errors, proper TypeScript types, clean imports
Preserves existing env vars & configs Yes Existing .env.example variables preserved, PostHog vars appended
No syntax or type errors Yes All TypeScript compiles correctly with proper type assertions
Correct imports/exports Yes All imports resolve correctly; posthog-js and posthog-node used appropriately
Minimal, focused changes Yes Changes are scoped to PostHog integration; no unrelated modifications

Issues

  • Missing newline at EOF: .env.example lacks a trailing newline, which is a minor style issue. [LOW]

Other completed criteria

  • Existing app logic preserved in all modified files
  • Error handling patterns maintained
  • No changes to database schema or auth flow
  • Build configuration is valid TypeScript

PostHog implementation: 3/5 ⚠️

Criteria Result Description
PostHog SDKs installed Yes posthog-js@^1.321.2 and posthog-node@^5.21.0 added to dependencies
PostHog client initialized Yes Client-side via instrumentation-client.ts with proper config; server-side singleton in lib/posthog-server.ts
capture() Yes Multiple events captured across auth, subscription, and team flows
identify() Yes User identified on sign-in/sign-up using email as distinctId
Error tracking Yes capture_exceptions: true enabled in client initialization
Reverse proxy Yes Properly configured in next.config.ts with /ingest routes to PostHog endpoints

Issues

  • Server-side events not flushed: In checkout.ts and webhook.ts, posthog.capture() is called but neither flush() nor shutdown() is called. In serverless/edge environments, events may be lost before the response is sent. Should call await posthog.flush() after capturing. [CRITICAL]
  • Inconsistent distinctId in webhook: webhook.ts uses Stripe customerId as distinctId while all other events use user email. This breaks user correlation and creates orphaned events in PostHog. Should look up user email from Stripe customer or subscription metadata. [MEDIUM]
  • Email as distinctId: Using email directly as distinctId works but creates issues if users change their email. Consider using a stable user ID instead. [LOW]

Other completed criteria

  • Proper posthog.reset() on sign-out
  • Debug mode enabled in development
  • ui_host configured for PostHog UI links
  • defaults: '2025-05-24' option included
  • skipTrailingSlashRedirect: true for API compatibility

PostHog insights and events: 4/5 ✅

Filename PostHog events Description
components/login.tsx user_signed_up, user_signed_in Captures authentication events with email; enables tracking sign-up conversion and user activation
components/header.tsx user_signed_out Tracks session end; useful for session duration analysis
pages/pricing.tsx pricing_viewed, checkout_started Top-of-funnel events for subscription conversion tracking with plan details
pages/api/stripe/checkout.ts checkout_completed Server-side capture of successful payments with full subscription context
pages/api/stripe/webhook.ts subscription_updated Tracks subscription lifecycle changes including cancellations
pages/dashboard/index.tsx subscription_managed, team_member_invited, team_member_removed Team engagement and subscription management events
pages/dashboard/general.tsx account_updated Profile update tracking
instrumentation-client.ts capturedException Automatic exception capture enabled

Issues

  • Missing page view tracking: No explicit `` capture or autocapture configuration. PostHog autocapture may handle this, but explicit configuration would be clearer. [LOW]
  • Limited enrichment on some events: account_updated only captures updated_fields statically as ['name', 'email'] rather than determining which fields actually changed. [LOW]

Other completed criteria

  • Events represent real user actions and product flows
  • Conversion funnel is trackable: pricing_viewedcheckout_startedcheckout_completed
  • Subscription lifecycle fully tracked for churn analysis
  • Team growth metrics captured with member counts
  • Event properties include relevant context for filtering and segmentation

Reviewed by wizard workbench PR evaluator

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

0 participants