Skip to content

[CI] (e2f7ab0) laravel/laravel12-saas#2429

Closed
wizard-ci-bot[bot] wants to merge 1 commit into
mainfrom
wizard-ci-e2f7ab0-laravel-laravel12-saas
Closed

[CI] (e2f7ab0) laravel/laravel12-saas#2429
wizard-ci-bot[bot] wants to merge 1 commit into
mainfrom
wizard-ci-e2f7ab0-laravel-laravel12-saas

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: laravel/laravel12-saas
App directory: apps/laravel/laravel12-saas
Workbench branch: wizard-ci-e2f7ab0-laravel-laravel12-saas
Wizard branch: release-please--branches--main--components--wizard
Context Mill branch: main
PostHog (MCP) branch: master
Timestamp: 2026-07-06T22:10:46.594Z
Duration: 585.5s

YARA Scanner

✓ 90 tool calls scanned, 0 violations detected

No violations: ✓ 90 clean scans

@wizard-ci-bot

wizard-ci-bot Bot commented Jul 6, 2026

Copy link
Copy Markdown
Author

PR Evaluation Report

Summary

This PR integrates PostHog into a Laravel 12 SaaS application by installing posthog/posthog-php, creating a PostHogService wrapper class, initializing PostHog in AppServiceProvider, adding request context middleware, wiring error tracking into bootstrap/app.php, and instrumenting 12 events across auth, billing, and profile flows.

Files changed Lines added Lines removed
19 +236 -16

Confidence score: 4/5 👍

  • Email used as distinctId everywhere: All capture() and identify() calls use ->email as the distinct ID. Emails are PII, can change (the app even supports email updates), and cause fragmented analytics. Should use ->id or another stable, non-PII identifier. [CRITICAL]
  • .env.example added to .gitignore: This prevents the example environment file from being tracked in version control, defeating its purpose as onboarding documentation for new developers. [MEDIUM]
  • Real API key committed in .env.example: The value phc_nmum...CV6a appears to be a real project token. .env.example should contain a placeholder like your_posthog_project_token_here. [MEDIUM]

File changes

Filename Score Description
app/Services/PostHogService.php 3/5 Wrapper service class with capture, identify, captureException, and feature flag methods. Uses deprecated isFeatureEnabled/getFeatureFlagPayload APIs.
app/Providers/AppServiceProvider.php 4/5 PostHog::init in boot() with config-driven API key and host — follows docs pattern
app/Http/Middleware/PostHogRequestContext.php 5/5 Request context middleware matching official docs pattern exactly
bootstrap/app.php 4/5 Error tracking via withExceptions callback, follows Laravel 11+ docs pattern
config/posthog.php 4/5 Dedicated config file using env() for all settings
.env.example 2/5 Contains real API key and is also added to .gitignore
composer.json 3/5 SDK added but with wildcard "*" version constraint
app/Http/Controllers/SubscriptionController.php 3/5 Good event coverage for billing funnel but uses email as distinctId
routes/auth.php 3/5 Logout tracking using email as distinctId
resources/views/livewire/pages/auth/forgot-password.blade.php 2/5 Uses hardcoded string 'anonymous' as distinctId

App sanity check ⚠️

Criteria Result Description
App builds and runs Yes No syntax errors; PHP and Blade files are valid
Preserves existing env vars & configs No .gitignore now excludes .env.example, preventing future tracking
No syntax or type errors Yes All PHP syntax is valid
Correct imports/exports Yes All use statements resolve to correct classes
Minimal, focused changes Yes All changes relate to PostHog integration
Pre-existing issues None No pre-existing issues identified

Issues

  • .env.example added to .gitignore: Adding .env.example to .gitignore means this file won't be tracked for future changes. This is counterproductive — .env.example exists specifically to document required environment variables for new developers. Remove this line from .gitignore. [MEDIUM]
  • Wildcard version constraint: "posthog/posthog-php": "*" allows any version including future major versions with breaking changes. Should pin to a specific range like "^4.9". [LOW]

Other completed criteria

  • Environment variables documented in .env.example (POSTHOG_PROJECT_TOKEN, POSTHOG_HOST, POSTHOG_DISABLED)
  • Build configuration is valid — composer.json is parseable and the package name is correct
  • Changes are minimal and focused on PostHog integration only

PostHog implementation ⚠️

Criteria Result Description
PostHog SDKs installed Yes posthog/posthog-php added to composer.json
PostHog client initialized Yes PostHog::init() in AppServiceProvider::boot() with config-driven key and host
capture() Yes 12 meaningful capture calls across auth, billing, and profile flows
identify() N/A Server-only app
Error tracking Yes PostHog::captureException() in bootstrap/app.php withExceptions callback, plus manual captureException in PostHogService
Reverse proxy N/A Server-only app

Issues

  • Email used as distinctId: Every capture() and identify() call uses ->email as the distinct ID. This is problematic because: (1) emails are PII and will appear in every event, (2) emails can change (the profile update form allows it), causing identity fragmentation, (3) the PHP SDK docs recommend using a stable user identifier. Should use (string) ->id instead. [CRITICAL]
  • Hardcoded 'anonymous' as distinctId: In forgot-password.blade.php, the password reset event uses 'anonymous' as a hardcoded string. All password reset requests from different users will be attributed to the same "person." Should use the email from the form input or a request-scoped identifier. [MEDIUM]
  • Real API key in .env.example: The token phc_nmum...CV6a appears to be a real PostHog project token. Should use a placeholder value. [MEDIUM]
  • Deprecated feature flag methods: PostHogService uses PostHog::isFeatureEnabled() and PostHog::getFeatureFlagPayload() which are deprecated in favor of PostHog::evaluateFlags(). [LOW]

Other completed criteria

  • API key loaded from environment variable via env('POSTHOG_PROJECT_TOKEN')
  • Host correctly configured via env('POSTHOG_HOST') with default https://us.i.posthog.com
  • PostHogRequestContext middleware correctly implements contextFromHeaders() and withContext() per docs
  • Config file uses env() with sensible defaults
  • PostHog initialization guarded by config check to avoid errors when key is missing

PostHog insights and events ⚠️

Filename PostHog events Description
register.blade.php user_signed_up Tracks new user registration with signup method
login.blade.php user_logged_in Tracks password-based login with login method
routes/auth.php user_logged_out Tracks user logout
SocialiteController.php social_login_completed Tracks social auth with provider and is_new_user flag
SubscriptionController.php subscription_page_viewed, subscription_started, subscription_plan_swapped, billing_portal_opened Full billing funnel coverage with plan details
Dashboard.php dashboard_viewed Tracks dashboard views with subscription status
update-profile-information-form.blade.php profile_updated Tracks profile changes with email_changed flag
delete-user-form.blade.php account_deleted Tracks account deletion before auth state is cleared
forgot-password.blade.php password_reset_requested Tracks password reset requests (but uses hardcoded 'anonymous' distinctId)
bootstrap/app.php captureException Automatic exception capture with URL and method context

Issues

  • PII as distinct ID: Using email addresses as distinctId means every event contains PII. Person properties like email should only be set via identify() or ``, not embedded in every capture call as the identifier. [CRITICAL]
  • account_deleted has no properties: The account deletion event has no enrichment properties (e.g., account age, subscription status). [LOW]

Other completed criteria

  • Events represent real user actions mapping to actual product flows (signup, login, subscription, profile management)
  • Events enable product insights — subscription funnel (page_viewed → started → swapped), auth flow (signup → login → logout), retention (dashboard_viewed)
  • Most events include relevant contextual properties (plan_name, provider, login_method, email_changed)
  • Event names are descriptive and follow 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