[CI] (1776c51) react-router/shopper#2734
Conversation
|
Now I have everything I need to evaluate. The PR Evaluation ReportSummaryThis PR integrates PostHog into a React Router v7 framework-mode e-commerce (shopper) app. It adds
Confidence score: 4/5 👍
File changes
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-nodedependency:posthog-nodeis added topackage.jsonbut no server-side PostHog code exists in the PR. Remove it to avoid unnecessary dependencies. [MEDIUM] - No
.env.example: Environment variablesVITE_POSTHOG_PROJECT_TOKENandVITE_POSTHOG_HOSTare not documented in a.env.examplefile. 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.noExternaladdition
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, {...})incheckout.tsxuses 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_headersinstead oftracing_headers: The init config uses__add_tracing_headers(an internal/private API prefixed with double underscores) instead of the documentedtracing_headersoption. 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 setvite.config.tscorrectly updated withssr.noExternalfor SSR compatibilityPostHogProvidercorrectly wraps the app inentry.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_idin identify: Incheckout.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_usedfires on every call tohandleSearchwhen 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
propertiesdicts — email/name correctly placed in identify person properties only
Reviewed by wizard workbench PR evaluator
Automated wizard CI run
Source: wizard-pr
Trigger ID:
1776c51App:
react-router/shopperApp directory:
apps/react-router/shopperWorkbench branch:
wizard-ci-1776c51-react-router-shopperWizard branch:
release-please--branches--main--components--wizardContext Mill branch:
mainPostHog (MCP) branch:
masterTimestamp: 2026-07-10T23:41:16.679Z
Duration: 216.5s
YARA Scanner