Skip to content

[CI] (97c6d9f) astro/astro-hybrid-marketing#2032

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

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

Conversation

@wizard-ci-bot

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

Copy link
Copy Markdown

Automated wizard CI run

Source: wizard-pr
Trigger ID: 97c6d9f
App: astro/astro-hybrid-marketing
App directory: apps/astro/astro-hybrid-marketing
Workbench branch: wizard-ci-97c6d9f-astro-astro-hybrid-marketing
Wizard branch: release-please--branches--main--components--wizard
Context Mill branch: main
PostHog (MCP) branch: master
Timestamp: 2026-06-23T15:35:47.955Z
Duration: 1139.5s

@wizard-ci-bot

wizard-ci-bot Bot commented Jun 23, 2026

Copy link
Copy Markdown
Author

PR Evaluation Report

Summary

This PR integrates PostHog into an Astro hybrid marketing site (NeuralFlow AI) by adding a client-side snippet component (posthog.astro) in the shared layout, a server-side posthog-node singleton for API route tracking, and meaningful event captures across homepage CTAs, pricing plans, contact form submissions, and navigation interactions.

Files changed Lines added Lines removed
11 +180 -7

Confidence score: 4/5 👍

  • No .env.example file: Environment variables PUBLIC_POSTHOG_PROJECT_TOKEN and PUBLIC_POSTHOG_HOST are used but not documented in a .env.example. Collaborators won't know what to set. [MEDIUM]
  • Email used as server-side distinctId fallback: In contact.ts, distinctId falls back to data.email (raw email as distinct ID), and the error handler uses the hardcoded string 'anonymous'. Both cause fragmented/merged person data in PostHog. [CRITICAL]
  • No posthog.identify() call: No user identification is implemented anywhere. The contact form collects user details but never calls identify(). [MEDIUM]
  • No reverse proxy configured: Client-side PostHog snippet loads directly from PostHog servers, making it susceptible to ad blockers. [MEDIUM]

File changes

Filename Score Description
src/components/posthog.astro 4/5 Client-side PostHog snippet with is:inline and define:vars for env var injection. Uses older snippet version without asset host replacement.
src/layouts/Layout.astro 5/5 Correctly imports and places PostHog component in <head>.
src/lib/posthog-server.ts 4/5 Server-side singleton pattern with shutdown helper. Uses PUBLIC_ prefixed env vars (appropriate for Astro).
src/pages/api/contact.ts 2/5 Server-side capture with session correlation headers, but distinctId falls back to raw email and uses hardcoded 'anonymous' in error path.
src/pages/index.astro 5/5 CTA click tracking with is:inline scripts and location/label properties.
src/pages/pricing.astro 5/5 Page view + plan selection tracking with data attributes and enriched properties.
src/pages/contact.astro 3/5 Form success/failure tracking and captureException for errors. Script is not is:inline, which may cause TypeScript issues with window.posthog.
src/components/Navigation.astro 5/5 Navigation CTA tracking with is:inline and location property.
package.json 4/5 Both posthog-js and posthog-node added. posthog-js is unnecessary since only the HTML snippet is used client-side.

App sanity check ⚠️

Criteria Result Description
App builds and runs Yes Vite/esbuild build pipeline doesn't type-check; app should build
Preserves existing env vars & configs Yes Existing code and configs preserved; only PostHog additions made
No syntax or type errors Yes No syntax errors; potential TypeScript issue with window.posthog in contact.astro's processed script noted below
Correct imports/exports Yes All imports resolve correctly (posthog-node, posthog-server, etc.)
Minimal, focused changes Yes All changes are PostHog-related
Pre-existing issues output: 'static' with @astrojs/node adapter is valid hybrid mode in Astro 5 No pre-existing issues affecting this PR

Issues

  • No .env.example file: PUBLIC_POSTHOG_PROJECT_TOKEN and PUBLIC_POSTHOG_HOST are required but not documented in any example file. The .env is gitignored. Create a .env.example with placeholder values. [MEDIUM]
  • window.posthog in processed script: contact.astro uses a regular <script> tag (not is:inline) that references window.posthog. With the strict TypeScript config, astro check will flag this. Should use is:inline or add a type declaration for window.posthog. [LOW]
  • Unnecessary posthog-js dependency: The client uses the HTML snippet approach which loads PostHog from the CDN. The posthog-js npm package is never imported on the client. Remove it from package.json or use the npm import approach instead of the snippet. [LOW]

Other completed criteria

  • All changes relate to PostHog integration
  • Correct files modified for Astro framework (component, layout, pages, server lib)
  • Code follows existing codebase patterns and conventions
  • Build configuration is valid

PostHog implementation ⚠️

Criteria Result Description
PostHog SDKs installed Yes posthog-js and posthog-node in package.json; HTML snippet used for client-side
PostHog client initialized Yes posthog.astro component uses snippet with is:inline and define:vars for env var injection, placed in Layout <head>
capture() Yes 11 meaningful events across pages and API routes
identify() No No posthog.identify() call anywhere. Contact form collects user data but doesn't identify users
Error tracking Yes captureException called in contact form catch block; server errors tracked via capture events
Reverse proxy No No reverse proxy configured; snippet loads directly from PostHog host

Issues

  • Raw email as distinctId fallback: In contact.ts line const distinctId = request.headers.get('X-PostHog-Distinct-Id') || data.email, the fallback uses the raw email address as a distinct ID. This causes fragmented person data and uses PII as an identifier. Use a generic fallback like 'server-anonymous' or skip the capture if no distinct ID header is present. [CRITICAL]
  • Hardcoded 'anonymous' distinct ID: The error handler in contact.ts uses distinctId: 'anonymous', which merges ALL server errors under a single fake person in PostHog. Use a unique identifier or skip the capture. [CRITICAL]
  • No identify() call: The framework docs state "Identifying users is required." The contact form is a natural place to call posthog.identify() with the user's email as person properties (not as the distinct_id). [MEDIUM]
  • No reverse proxy: Client-side analytics may be blocked by ad blockers. Configure a reverse proxy or PostHog's managed proxy for more reliable data collection. [MEDIUM]
  • Older snippet version: The snippet in posthog.astro uses s.api_host+"/static/array.js" instead of the newer s.api_host.replace(".i.posthog.com","-assets.i.posthog.com")+"/static/array.js" pattern from the docs. This works but may not route to the optimal asset CDN. [LOW]

Other completed criteria

  • API key loaded from PUBLIC_POSTHOG_PROJECT_TOKEN environment variable
  • API host loaded from PUBLIC_POSTHOG_HOST environment variable
  • is:inline directive used on PostHog script tags (in posthog.astro, index, pricing, navigation)
  • PUBLIC_ prefix used for client-side env vars per Astro conventions
  • PostHog component imported in Layout and wraps all pages
  • Server-side PostHog uses singleton pattern with proper shutdown
  • Session ID correlation between client and server via custom headers

PostHog insights and events ✅

Filename PostHog events Description
src/pages/index.astro cta_clicked, contact_sales_clicked Hero section CTA engagement tracking with location properties
src/pages/pricing.astro pricing_page_viewed, pricing_plan_selected, enterprise_contact_clicked Full pricing funnel: page view → plan selection with plan/price properties
src/pages/contact.astro contact_form_submitted, contact_form_failed, captureException Form submission success/failure tracking with interest and error properties
src/components/Navigation.astro get_started_clicked Nav CTA tracking with location property
src/pages/api/contact.ts contact_form_received, contact_form_validation_failed, contact_form_server_error Server-side form processing tracking with validation reason properties

Issues

  • No issues with event quality. Events are well-structured and enable meaningful funnels.

Other completed criteria

  • Events represent real user actions (CTA clicks, page views, form submissions)
  • Events enable product insights (pricing funnel, CTA engagement trends, form success rates)
  • Events include relevant properties (plan, price, location, interest, reason, status)
  • No PII in event properties (email/name not included in capture properties)
  • Event names are descriptive and use 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