Skip to content

[CI] (3f39e0e) stripe/stripe-next-js-saas-starter - #4182

Closed
wizard-ci-bot[bot] wants to merge 1 commit into
mainfrom
wizard-ci-3f39e0e-stripe-stripe-next-js-saas-starter
Closed

wizard-ci-bot[bot] wants to merge 1 commit into
mainfrom
wizard-ci-3f39e0e-stripe-stripe-next-js-saas-starter

Conversation

@wizard-ci-bot

@wizard-ci-bot wizard-ci-bot Bot commented Sep 23, 2026

Copy link
Copy Markdown

Automated wizard CI run

Source: wizard-pr
Trigger ID: 3f39e0e
App: stripe/stripe-next-js-saas-starter
App directory: apps/stripe/stripe-next-js-saas-starter
Workbench branch: wizard-ci-3f39e0e-stripe-stripe-next-js-saas-starter
Wizard branch: release-please--branches--main--components--wizard
Context Mill branch: main
PostHog (MCP) branch: master
Timestamp: 2026-09-23T22:26:08.480Z
Duration: 138.5s

YARA Scanner

✓ 36 tool calls scanned, 0 violations detected

No violations: ✓ 36 clean scans

@wizard-ci-bot

wizard-ci-bot Bot commented Sep 23, 2026

Copy link
Copy Markdown
Author

Now I have a complete picture. Let me write the evaluation.


PR Evaluation Report

Summary

This PR from the revenue-analytics wizard adds posthog_person_distinct_id metadata to Stripe checkout sessions and subscription data in a single file (lib/payments/stripe.ts). The change is extremely minimal (+9/-2 lines). The broader PostHog integration (SDK installation, initialization, reverse proxy, identify, capture events, error tracking) already exists in the codebase and was not modified by this PR.

Files changed Lines added Lines removed
1 +9 -2

Confidence score: 4/5 👍

  • Webhook handler uses wrong distinctId: The webhook at app/api/stripe/webhook/route.ts captures subscription_updated and subscription_canceled events using customerId (Stripe customer ID like cus_xxx) as the distinctId, while the client-side identify() uses String(user.id) (database ID). These events will create orphaned person records in PostHog that don't link to real users. The posthog_person_distinct_id metadata added by this PR exists specifically to solve this — but the webhook handler was never updated to read it. [CRITICAL]
  • Environment variables not documented: .env.example does not include NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN or NEXT_PUBLIC_POSTHOG_HOST. The server-side client (lib/posthog-server.ts) reads NEXT_PUBLIC_POSTHOG_HOST which may be undefined if not set. [MEDIUM]

File changes

Filename Score Description
lib/payments/stripe.ts 3/5 Adds posthog_person_distinct_id metadata to Stripe checkout session and subscription, and uses it for client_reference_id. Change is correct and clean but the metadata is never consumed by the webhook handler.

App sanity check ✅

Criteria Result Description
App builds and runs Yes Syntactically valid TypeScript, no new dependencies
Preserves existing env vars & configs Yes Only adds new fields; client_reference_id value changed from user.id.toString() to the equivalent posthogDistinctId (same value)
No syntax or type errors Yes Clean TypeScript
Correct imports/exports Yes No new imports needed
Minimal, focused changes Yes Only 9 lines added, 2 removed in one file
Pre-existing issues .env.example missing PostHog vars; webhook handler uses Stripe customerId as distinctId

Issues

  • Environment variables not documented in .env.example: NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN and NEXT_PUBLIC_POSTHOG_HOST are used across the codebase but not listed in .env.example. New developers or deployments will have no reference for required PostHog configuration. [MEDIUM]

Other completed criteria

  • App builds without errors — the change is additive and syntactically valid
  • Existing functionality preserved — client_reference_id value is equivalent (user.id.toString() → String(user.id))
  • Build configuration unchanged and valid

PostHog implementation ⚠️

Criteria Result Description
PostHog SDKs installed Yes posthog-js@^1.369.0 and posthog-node@^5.29.2 in package.json
PostHog client initialized Yes instrumentation-client.ts calls posthog.init() with env var token and /ingest reverse proxy host
capture() Yes checkout_completed in checkout route, subscription_updated/subscription_canceled in webhook
identify() Yes Dashboard layout identifies with String(userData.id) and person properties {email, name}; calls posthog.reset() on sign-out
Error tracking Yes capture_exceptions: true in init config
Reverse proxy Yes next.config.ts rewrites /ingest/static/* → us-assets.i.posthog.com and /ingest/* → us.i.posthog.com

Issues

  • Webhook distinctId mismatch — metadata added but never consumed: The PR adds posthog_person_distinct_id metadata to the Stripe subscription, but the webhook handler at app/api/stripe/webhook/route.ts still uses subscription.customer (Stripe customer ID) as the distinctId. This means subscription_updated and subscription_canceled events are attributed to cus_xxx instead of the user's actual PostHog distinct ID (String(user.id)). The metadata this PR adds exists precisely to fix this, but the webhook handler was never updated to read subscription.metadata.posthog_person_distinct_id. Revenue attribution will be broken for all subscription lifecycle events. [CRITICAL]

Other completed criteria

  • API key loaded from NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN environment variable, not hardcoded
  • Host configured via reverse proxy (/ingest) on client-side and env var on server-side
  • Reverse proxy correctly routes both /ingest/static/* (assets) and /ingest/* (ingestion)
  • posthog.reset() called on logout
  • Identify uses stable database ID (String(userData.id)) with email/name as person properties

PostHog insights and events ⚠️

Filename PostHog events Description
lib/payments/stripe.ts (metadata only) Adds posthog_person_distinct_id to Stripe session and subscription metadata for linking Stripe events to PostHog persons
app/api/stripe/checkout/route.ts checkout_completed Captures checkout completion with plan_name, product_id, subscription_id, status — uses correct String(user.id) distinct ID
app/api/stripe/webhook/route.ts subscription_updated, subscription_canceled Captures subscription lifecycle events but uses Stripe customerId as distinctId — broken attribution
app/(dashboard)/layout.tsx identify, reset Identifies user on dashboard load with database ID; resets on sign-out

Issues

  • Subscription events attributed to wrong person: subscription_updated and subscription_canceled events use Stripe customer ID (cus_xxx) as distinctId. These create orphaned person records that don't link to the identified user (String(user.id)). The webhook handler should read subscription.metadata.posthog_person_distinct_id and use that as the distinctId instead. [CRITICAL]

Other completed criteria

  • Events represent real user actions (checkout, subscription changes)
  • Events include rich properties (plan_name, product_id, subscription_status, stripe_customer_id)
  • No PII in capture() properties — email is only in identify() person properties
  • Event names are descriptive and use consistent snake_case convention
  • Checkout event enables revenue funnel analysis (pricing → checkout → completion)

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