Skip to content

[CI] (e2f7ab0) astro/astro-hybrid-marketing#2417

Closed
wizard-ci-bot[bot] wants to merge 1 commit into
mainfrom
wizard-ci-e2f7ab0-astro-astro-hybrid-marketing
Closed

[CI] (e2f7ab0) astro/astro-hybrid-marketing#2417
wizard-ci-bot[bot] wants to merge 1 commit into
mainfrom
wizard-ci-e2f7ab0-astro-astro-hybrid-marketing

Conversation

@wizard-ci-bot

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

Copy link
Copy Markdown

Automated wizard CI run

Source: wizard-pr
Trigger ID: e2f7ab0
App: astro/astro-hybrid-marketing
App directory: apps/astro/astro-hybrid-marketing
Workbench branch: wizard-ci-e2f7ab0-astro-astro-hybrid-marketing
Wizard branch: release-please--branches--main--components--wizard
Context Mill branch: main
PostHog (MCP) branch: master
Timestamp: 2026-07-06T21:58:47.572Z
Duration: 413.7s

YARA Scanner

✓ 51 tool calls scanned, 0 violations detected

No violations: ✓ 51 clean scans

@wizard-ci-bot

wizard-ci-bot Bot commented Jul 6, 2026

Copy link
Copy Markdown
Author

Now I have all the context needed. Let me produce the evaluation.


PR Evaluation Report

Summary

This PR integrates PostHog into an Astro hybrid marketing site (NeuralFlow AI) using both a client-side HTML snippet component (posthog.astro) included in the root layout and a server-side posthog-node singleton for API route tracking. Events are captured across CTA buttons, pricing page views, plan selection, and contact form submission, with user identification on form submit.

Files changed Lines added Lines removed
11 +153 -7

Confidence score: 4/5 👍

  • Email used as distinct_id: Both client-side posthog.identify(data.email, ...) and server-side posthog.identify({ distinctId: data.email, ... }) use the raw email address as the distinct ID. This causes fragmented user data — anonymous pre-identification events won't merge properly on the server, and email addresses aren't stable identifiers. Use a database user ID or let the client-side anonymous ID flow through. [CRITICAL]
  • Server-side captureException API likely incorrect: getPostHogServer().captureException(error as Error, 'anonymous')posthog-node's error capture API doesn't match this signature. The standard approach for server-side exception capture in posthog-node is to use the context-based pattern or capture a `` event manually. This call will likely fail silently. [MEDIUM]
  • No .env.example documenting required env vars: PUBLIC_POSTHOG_PROJECT_TOKEN and PUBLIC_POSTHOG_HOST are required but only mentioned in the setup report as a TODO. Collaborators won't know what to set. [MEDIUM]
  • No reverse proxy configured: The client-side snippet loads PostHog directly from the API host, making it susceptible to ad blockers. No proxy rewrites or middleware are set up. [MEDIUM]

File changes

Filename Score Description
src/components/posthog.astro 4/5 New PostHog snippet component with is:inline and define:vars for env passthrough. Uses an older snippet version.
src/layouts/Layout.astro 5/5 Imports and adds PostHog component in <head> — correct placement.
src/lib/posthog-server.ts 4/5 Server-side singleton with flushAt: 1 / flushInterval: 0. Uses PUBLIC_ env vars for server code (works but unconventional).
src/pages/api/contact.ts 2/5 Server-side identify and capture, but uses email as distinct_id and has likely incorrect captureException API.
src/pages/contact.astro 3/5 Client-side identify and capture on form submit, plus error tracking. Uses email as distinct_id.
src/pages/index.astro 5/5 Clean CTA click tracking with inline scripts and is:inline.
src/pages/pricing.astro 5/5 Page view and plan CTA tracking with data-plan attribute enrichment.
src/components/Navigation.astro 5/5 Nav CTA click tracking with proper inline script pattern.
package.json 4/5 Adds posthog-js and posthog-node. posthog-js is unnecessary since the script tag snippet is used.
.gitignore 5/5 Adds .env to gitignore.
posthog-setup-report.md 4/5 Useful report but shouldn't be a substitute for actual .env.example.

App sanity check ⚠️

Criteria Result Description
App builds and runs Yes No syntax errors; inline scripts and imports are valid
Preserves existing env vars & configs Yes Existing app code untouched; only PostHog additions
No syntax or type errors Yes All TypeScript and Astro syntax is valid
Correct imports/exports Yes posthog-node import in server lib, component imports in layout correct
Minimal, focused changes Yes All changes are PostHog-related
Pre-existing issues None Base app appears functional

Issues

  • No .env.example file: PUBLIC_POSTHOG_PROJECT_TOKEN and PUBLIC_POSTHOG_HOST are required environment variables but no .env.example or equivalent documentation is committed. The setup report mentions this as a TODO but it should have been included. [MEDIUM]
  • Unnecessary posthog-js dependency: posthog-js is added to package.json but never imported — the client-side integration uses the HTML script tag snippet exclusively. This adds unnecessary bundle weight. [LOW]

Other completed criteria

  • All changes are PostHog-related (no unrelated edits)
  • Correct files modified for Astro framework (component, layout, pages, server lib)
  • Code follows existing codebase patterns (inline scripts, Astro component conventions)
  • .env added to .gitignore
  • Build configuration (package.json) is valid

PostHog implementation ⚠️

Criteria Result Description
PostHog SDKs installed Yes posthog-js and posthog-node in package.json; client uses HTML snippet (script tag approach)
PostHog client initialized Yes Snippet in posthog.astro with is:inline, included in Layout <head>. Server singleton in posthog-server.ts
capture() Yes 7 meaningful events across pages (CTAs, page views, form submissions)
identify() No Uses raw email as distinct_id on both client and server, causing fragmented data
Error tracking No Client-side captureException is correct, but server-side captureException(error, 'anonymous') uses incorrect posthog-node API signature
Reverse proxy No Not configured; snippet loads directly from PostHog API host

Issues

  • Email as distinct_id: posthog.identify(data.email, { name: data.name }) on the client and posthog.identify({ distinctId: data.email, ... }) on the server both use the raw email address as the distinct ID. This creates fragmented user profiles — the anonymous session events captured before identification won't properly merge on the server side, and email is not a stable identifier. Use a database user ID instead, and pass email only as a person property. [CRITICAL]
  • Server-side captureException API mismatch: getPostHogServer().captureException(error as Error, 'anonymous') — the posthog-node SDK's captureException does not accept (error, distinctId) as arguments. This call will likely throw or silently fail. For server-side error capture, use posthog.capture({ distinctId: '...', event: '', properties: { : error.message, ... } }) or ensure you're using the correct posthog-node error tracking API. [MEDIUM]
  • Reverse proxy not configured: No proxy setup to route PostHog requests through the app's domain. Client-side tracking is vulnerable to ad blockers. [MEDIUM]
  • Outdated defaults date: The snippet uses defaults: '2026-01-30' while the latest documented value is '2026-05-30'. [LOW]
  • Older snippet version: The script tag uses s.api_host+"/static/array.js" instead of the newer pattern that routes through the assets origin (s.api_host.replace(".i.posthog.com", "-assets.i.posthog.com") + "/static/array.js"). [LOW]

Other completed criteria

  • API key loaded from environment variable (PUBLIC_POSTHOG_PROJECT_TOKEN)
  • Host correctly configured with fallback to https://us.i.posthog.com
  • is:inline directive used correctly on all PostHog script tags per Astro rules
  • PUBLIC_ prefix used for client-side env vars per Astro conventions
  • PostHog component imported in Layout and applied to all pages
  • Server-side singleton pattern with flushAt: 1 for immediate flushing
  • Session ID passed from client to server via custom header

PostHog insights and events ⚠️

Filename PostHog events Description
src/pages/index.astro free_trial_cta_clicked, contact_sales_clicked Hero CTA button clicks with location: 'hero' property
src/components/Navigation.astro nav_cta_clicked Navigation "Get Started" button click with location: 'navigation'
src/pages/pricing.astro pricing_page_viewed, pricing_plan_cta_clicked Page view event and plan CTA clicks with plan property (starter/pro/enterprise)
src/pages/contact.astro contact_form_submitted, captureException Form submission with interest and has_company properties; client-side error capture
src/pages/api/contact.ts contact_form_received, captureException Server-side form receipt with interest, has_company, source properties; server-side error capture (incorrect API)

Issues

  • No PII concerns in capture events: Events correctly keep PII (email, name) in identify() person properties only and use non-PII properties (interest, has_company, plan, location) in capture calls. However, the identify() distinct_id issue described above still applies. [CRITICAL — covered above]

Other completed criteria

  • Events represent real user actions mapped to actual product flows (CTA clicks, page views, form submissions)
  • Events enable product insights — can build funnels: pricing_page_viewed → pricing_plan_cta_clicked → contact_form_submitted → contact_form_received
  • Events include relevant contextual properties (plan name, location, interest type, has_company)
  • No PII in event properties — email and name only in person properties via identify()
  • Event names are descriptive, consistent snake_case convention

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