Skip to content

[CI] (1776c51) react-router/shopper#2734

Closed
wizard-ci-bot[bot] wants to merge 1 commit into
mainfrom
wizard-ci-1776c51-react-router-shopper
Closed

[CI] (1776c51) react-router/shopper#2734
wizard-ci-bot[bot] wants to merge 1 commit into
mainfrom
wizard-ci-1776c51-react-router-shopper

Conversation

@wizard-ci-bot

@wizard-ci-bot wizard-ci-bot Bot commented Jul 10, 2026

Copy link
Copy Markdown

Automated wizard CI run

Source: wizard-pr
Trigger ID: 1776c51
App: react-router/shopper
App directory: apps/react-router/shopper
Workbench branch: wizard-ci-1776c51-react-router-shopper
Wizard branch: release-please--branches--main--components--wizard
Context Mill branch: main
PostHog (MCP) branch: master
Timestamp: 2026-07-10T23:41:16.679Z
Duration: 216.5s

YARA Scanner

✓ 70 tool calls scanned, 0 violations detected

No violations: ✓ 70 clean scans

@wizard-ci-bot

wizard-ci-bot Bot commented Jul 10, 2026

Copy link
Copy Markdown
Author

Now I have everything I need to evaluate. The .env exists but there's no .env.example. The tracing option uses __add_tracing_headers (internal API name) instead of the documented tracing_headers. Let me also note the API key is hardcoded in .env which is committed but that's a pre-existing file pattern.


PR Evaluation Report

Summary

This PR integrates PostHog into a React Router v7 framework-mode e-commerce (shopper) app. It adds posthog-js and @posthog/react initialization via entry.client.tsx, wraps the app with PostHogProvider, adds error tracking in the root error boundary, and instruments 11 custom events across the full shopping funnel (browsing, search, product views, cart operations, checkout). User identification is performed at checkout via posthog.identify().

Files changed Lines added Lines removed
10 +196 -9

Confidence score: 4/5 👍

  • Email used as distinct_id: posthog?.identify(formData.email, ...) uses a raw email address as the distinct ID, which causes fragmented data if users change email addresses and is flagged by PostHog best practices. Use a stable internal user ID instead. [CRITICAL]
  • No reverse proxy configured: Client-side PostHog requests go directly to us.i.posthog.com and are susceptible to ad blocker interception. [MEDIUM]
  • posthog-node installed but unused: The posthog-node package is added to package.json but no server-side PostHog code exists in the committed files, adding unnecessary bundle weight. [MEDIUM]

File changes

Filename Score Description
app/entry.client.tsx 4/5 New file: initializes PostHog with env vars, wraps app in PostHogProvider. Uses __add_tracing_headers instead of documented tracing_headers.
app/root.tsx 4/5 Adds captureException(error) in ErrorBoundary — correct pattern per React Router framework mode docs.
app/context/CartContext.tsx 4/5 Instruments cart operations with well-structured events and properties.
app/routes/products.tsx 3/5 Adds products_browsed in useEffect and search/category tracking. Search tracking fires on every keystroke ≥2 chars (not debounced).
app/routes/products..tsx 4/5 Adds product_viewed event in useEffect — legitimate for page-view tracking.
app/routes/cart.tsx 5/5 Clean checkout_started capture in click handler with good properties.
app/routes/checkout.tsx 2/5 identify() uses email as distinct_id; captures checkout events with good properties otherwise.
package.json 3/5 Adds posthog-js, @posthog/react (needed), and posthog-node (unused).
vite.config.ts 5/5 Correctly adds noExternal for SSR compatibility per docs.
posthog-setup-report.md 3/5 Setup report with event table and next steps — informational but not code.

App sanity check ⚠️

Criteria Result Description
App builds and runs Yes Syntax is valid, imports resolve, no type errors visible
Preserves existing env vars & configs Yes Existing code preserved; only PostHog additions
No syntax or type errors Yes All changed files have valid syntax and correct types
Correct imports/exports Yes @posthog/react and posthog-js imports are correct
Minimal, focused changes No posthog-node added to dependencies but never used in any committed file
Pre-existing issues .env contains a real API key (phc_xxxx...CV6a) committed to the repo Pre-existing; not introduced by this PR

Issues

  • Unused posthog-node dependency: posthog-node is added to package.json but no server-side PostHog code exists in the PR. Remove it to avoid unnecessary dependencies. [MEDIUM]
  • No .env.example: Environment variables VITE_POSTHOG_PROJECT_TOKEN and VITE_POSTHOG_HOST are not documented in a .env.example file. Collaborators won't know which env vars to set. [LOW]

Other completed criteria

  • App builds without errors — all syntax and imports are valid
  • Existing app code and configs are preserved
  • No syntax or type errors introduced
  • All import/export statements resolve correctly
  • Build configuration (vite.config.ts) is valid with correct ssr.noExternal addition

PostHog implementation ⚠️

Criteria Result Description
PostHog SDKs installed Yes posthog-js and @posthog/react added to package.json
PostHog client initialized Yes posthog.init() in entry.client.tsx with PostHogProvider wrapping HydratedRouter — correct React Router framework mode pattern
capture() Yes 11 distinct capture calls across shopping funnel
identify() No Uses formData.email as distinct_id — raw email as distinct ID causes fragmented data; should use a stable user ID
Error tracking Yes posthog?.captureException(error) in root ErrorBoundary — matches React Router framework mode docs
Reverse proxy No No reverse proxy configured; api_host points directly to us.i.posthog.com

Issues

  • Email as distinct_id: posthog?.identify(formData.email, {...}) in checkout.tsx uses the user's raw email address as the distinct ID. If a user changes their email, they become a new person in PostHog. Use a stable internal user/account ID instead. [CRITICAL]
  • No reverse proxy: Client-side requests go directly to us.i.posthog.com, making them vulnerable to ad blocker interception. Configure Next.js rewrites or a managed proxy. [MEDIUM]
  • __add_tracing_headers instead of tracing_headers: The init config uses __add_tracing_headers (an internal/private API prefixed with double underscores) instead of the documented tracing_headers option. While it may work, it's undocumented and could break without notice. [MEDIUM]

Other completed criteria

  • PostHog SDK correctly installed via package.json
  • API key loaded from environment variable (VITE_POSTHOG_PROJECT_TOKEN)
  • Host correctly configured from environment variable (VITE_POSTHOG_HOST)
  • defaults: "2026-05-30" correctly set
  • vite.config.ts correctly updated with ssr.noExternal for SSR compatibility
  • PostHogProvider correctly wraps the app in entry.client.tsx
  • Error boundary correctly captures exceptions using captureException

PostHog insights and events ⚠️

Filename PostHog events Description
app/routes/products.tsx products_browsed, product_search_used, product_category_selected Catalog browsing, search, and filter tracking with product/category counts
app/routes/products..tsx product_viewed Product detail page view with product metadata
app/context/CartContext.tsx product_added_to_cart, cart_item_removed, cart_quantity_updated, cart_cleared Full cart lifecycle tracking with quantities and totals
app/routes/cart.tsx checkout_started Checkout funnel entry with cart summary
app/routes/checkout.tsx checkout_submitted, checkout_completed Checkout completion funnel with order values
app/root.tsx captureException Unhandled error/exception tracking via ErrorBoundary

Issues

  • Email as distinct_id in identify: In checkout.tsx, posthog?.identify(formData.email, {...}) uses email as the distinct ID. This is PII used as a fabricated distinct_id, which fragments user data if emails change. [CRITICAL]
  • Search event fires on every keystroke: product_search_used fires on every call to handleSearch when the term is ≥2 characters. Since this is bound to input changes, it will generate excessive events without debouncing. [LOW]

Other completed criteria

  • Events represent real user actions across a complete shopping funnel
  • Events enable product insights — a full funnel from browse → view → cart → checkout is instrumentable
  • Events include rich, relevant properties (product IDs, categories, prices, quantities, cart totals)
  • Event names are descriptive and use consistent snake_case convention
  • No PII in event properties dicts — email/name correctly placed in identify person properties only

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