Skip to content

[CI] (1776c51) astro/astro-hybrid-marketing#2712

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

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

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: astro/astro-hybrid-marketing
App directory: apps/astro/astro-hybrid-marketing
Workbench branch: wizard-ci-1776c51-astro-astro-hybrid-marketing
Wizard branch: release-please--branches--main--components--wizard
Context Mill branch: main
PostHog (MCP) branch: master
Timestamp: 2026-07-10T23:20:32.338Z
Duration: 508.4s

YARA Scanner

✓ 61 tool calls scanned, 0 violations detected

No violations: ✓ 61 clean scans

@wizard-ci-bot

wizard-ci-bot Bot commented Jul 10, 2026

Copy link
Copy Markdown
Author

PR Evaluation Report

Summary

This PR integrates PostHog into an Astro hybrid marketing site using the HTML snippet approach for client-side tracking and posthog-node for server-side event capture on the contact API route. It adds a reusable posthog.astro component in the layout, instruments CTA clicks across pages, and captures contact form submissions on both client and server with identify flows.

Files changed Lines added Lines removed
11 +276 -14

Confidence score: 4/5 👍

  • Server-side singleton destroyed by shutdown(): The getPostHogServer() returns a singleton, but posthog.shutdown() is called at the end of each request. After the first request, the cached posthogClient reference points to a dead client — subsequent requests silently lose events. Should use posthog.flush() or set posthogClient = null after shutdown. [CRITICAL]
  • Email used as distinct_id in client-side identify: posthog.identify(email, {...}) on the contact page uses the raw email address as the distinct ID, which causes fragmented data when the same user submits from different browsers. Should use the existing anonymous distinct ID and set email via person properties only. [CRITICAL]
  • No reverse proxy configured: Client-side events are sent directly to us.i.posthog.com, making them vulnerable to ad blockers on a marketing site where tracking is critical. [MEDIUM]

File changes

Filename Score Description
src/components/posthog.astro 4/5 New PostHog snippet component using is:inline and define:vars — correct Astro pattern. Uses slightly older snippet (missing assets URL optimization).
src/layouts/Layout.astro 5/5 Imports and adds PostHog component in <head> — correct placement.
src/lib/posthog-server.ts 2/5 Server singleton, but shutdown in request handler destroys the shared instance; enableExceptionAutocapture is not a valid posthog-node option.
src/pages/api/contact.ts 3/5 Good event coverage with session linking, but shutdown() kills the singleton and identify correctly uses header distinct_id.
src/pages/contact.astro 3/5 Client-side form tracking with identify and error capture, but uses email as distinct_id.
src/pages/index.astro 5/5 Clean event delegation for hero CTAs with enriched properties.
src/pages/pricing.astro 5/5 Well-structured CTA tracking with plan and type properties.
src/components/Navigation.astro 5/5 Navigation CTA tracking via data attributes and event delegation.
src/components/Footer.astro 5/5 Footer link click tracking with delegation pattern.
package.json 4/5 Both posthog-js and posthog-node added; posthog-js is unnecessary since the snippet loads from CDN, but not harmful.
posthog-setup-report.md Wizard report file, not evaluated.

App sanity check ⚠️

Criteria Result Description
App builds and runs Yes No syntax or type errors; all files are valid Astro/TS
Preserves existing env vars & configs Yes Existing config untouched; removed PII from console.log (improvement)
No syntax or type errors Yes All changed files have valid syntax
Correct imports/exports Yes posthog-node import and Astro component imports are correct
Minimal, focused changes Yes All changes serve PostHog integration
Pre-existing issues None Base app is clean

Issues

  • No .env.example committed: Environment variables PUBLIC_POSTHOG_PROJECT_TOKEN and PUBLIC_POSTHOG_HOST are used but not documented in a committed example file. Collaborators won't know which vars to set. [MEDIUM]

Other completed criteria

  • Build configuration valid — package.json dependencies parse correctly
  • Existing app code and configs preserved
  • Changes are minimal and focused on PostHog integration

PostHog implementation ⚠️

Criteria Result Description
PostHog SDKs installed Yes posthog-js and posthog-node in package.json; client uses HTML snippet (loads from CDN)
PostHog client initialized Yes Client: snippet in posthog.astro with is:inline + define:vars; Server: singleton in posthog-server.ts
capture() Yes 10 distinct events across client and server covering CTAs, form submissions, validation failures, and server errors
identify() No Client-side uses raw email as distinct_id; server-side correctly uses header-provided distinct ID
Error tracking Yes captureException() on both client (contact form catch) and server (API error handler)
Reverse proxy No Not configured; client-side events go directly to us.i.posthog.com

Issues

  • posthog.shutdown() destroys server singleton: getPostHogServer() caches the client in a module-level variable, but shutdown() is called on every request (lines 98, 124 of contact.ts). After the first request completes, the cached reference points to a terminated client. All subsequent requests silently drop events. Fix: use await posthog.flush() instead of shutdown(), or set posthogClient = null after shutdown so the next call recreates the client. [CRITICAL]
  • Email as distinct_id in client-side identify: window.posthog?.identify(email, { email, name, ... }) in contact.astro uses the user's email address as their distinct ID. This causes fragmented person profiles when the same user submits from multiple devices. The correct pattern is posthog.identify(someStableUserId, { email }) or to use posthog.setPersonProperties({ email }) without changing the distinct ID. [CRITICAL]
  • No reverse proxy: Marketing sites are especially susceptible to ad blockers. Without a reverse proxy, conversion tracking events (the core value of this integration) may be silently blocked. [MEDIUM]
  • Older snippet version: The snippet loads the SDK from api_host + '/static/array.js' instead of the newer pattern using api_host.replace(".i.posthog.com", "-assets.i.posthog.com") + "/static/array.js" which routes through the assets CDN. [LOW]
  • enableExceptionAutocapture not a valid posthog-node option: This config key in posthog-server.ts is a posthog-js browser option, not a posthog-node option. It will be silently ignored. [LOW]

Other completed criteria

  • API key loaded from environment variable (PUBLIC_POSTHOG_PROJECT_TOKEN)
  • Host correctly configured (PUBLIC_POSTHOG_HOSThttps://us.i.posthog.com)
  • Uses correct Astro PUBLIC_ prefix for client-side env vars
  • is:inline directive used correctly on all PostHog script tags
  • PostHog component created in src/components/ and imported in Layout (matches Astro docs pattern)
  • Server-side distinct ID correctly extracted from X-POSTHOG-DISTINCT-ID header
  • Session ID forwarded via X-POSTHOG-SESSION-ID header for cross-client/server linkage

PostHog insights and events ✅

Filename PostHog events Description
src/pages/index.astro cta_clicked Tracks hero CTA clicks with label, location, and destination properties
src/pages/pricing.astro pricing_cta_clicked, contact_sales_clicked Tracks pricing plan CTA interactions with plan name and CTA type
src/pages/contact.astro contact_form_submitted, contact_form_submission_failed Client-side form success/failure with interest and submission context
src/pages/api/contact.ts contact_form_received, contact_form_validation_failed, contact_form_server_error, captureException Server-side form processing events covering success, validation errors, and unexpected errors
src/components/Navigation.astro navigation_cta_clicked Tracks "Get Started" navigation CTA with location and path
src/components/Footer.astro footer_link_clicked Tracks footer link clicks with link text, destination, and current path

Issues

No event quality issues.

Other completed criteria

  • Events represent real user actions in a marketing funnel (CTA clicks → form submission → server receipt)
  • Events enable product insights — can build CTA conversion funnels, form completion rates, and failure analysis
  • All events include enriched contextual properties (plan, location, interest, path)
  • No PII in capture event properties — email/name only set via identify() person properties
  • Event names are descriptive, consistent snake_case, and clearly describe the action

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