posthog/posthog-php
PostHog PHP SDK for server-side product analytics: capture events, identify users, group accounts, evaluate feature flags, and send data to PostHog from Laravel or plain PHP applications.
Architecture fit. posthog/posthog-php is a thin server-side SDK, not a Laravel package. It is a small HTTP wrapper around PostHog's /capture, /decide, and related endpoints, with no service provider, facade, config publishing, or framework coupling. That is actually good news for Laravel: it slots in as an infrastructure dependency behind your own domain-level analytics interface rather than dictating application structure. It is a poor fit if a stakeholder expects "install and it instruments the app" — there is no out-of-the-box request/event middleware, no Eloquent hooks, and no Blade/Inertia integration. Treat it as a transport client, and budget for a small adapter layer.
Integration feasibility. High. It is a Composer package under the official PostHog org, MIT-licensed, and only depends on a PSR HTTP stack. A singleton binding in a service provider plus an config/posthog.php and env vars covers the bulk of the work. The real effort is not installation but deciding the event taxonomy, identity strategy (distinct_id for authenticated users vs. anonymous IDs), and where in the request lifecycle capture calls are allowed to fire.
Technical risk. The dominant risks are operational, not code-quality:
Key questions.
Stack fit. Laravel 9–12 / PHP 8.1+ is a comfortable fit; the SDK has no Laravel version constraints of its own. The main structural decision is to wrap it: create an Analytics contract in your domain layer with capture(), identify(), isFeatureEnabled(), and bind the PostHog client as the driver. This keeps testability (swap for a fake in tests), makes the SDK replaceable, and gives you one place to enforce timeouts, sampling, and PII scrubbing.
Migration path. If replacing an existing tool, do not cut over at once. Run PostHog in shadow mode alongside the incumbent for a sprint, diff event volumes and identity resolution, then flip. If this is greenfield, start with a deliberately small event set (signup, activation, core value action, subscription) rather than auto-instrumenting everything — retrofitting a taxonomy is far more expensive than extending one.
Compatibility. Confirm the SDK's supported PHP matrix against your oldest supported runtime, especially if you run a matrix across 8.1→8.4. Under Octane or other long-lived workers, verify the client is stateless and safe to hold as a singleton (it is, but confirm the HTTP client's connection reuse behaviour). Ensure config is env-driven and cache-safe (config:cache must not bake in a stale key). If flags are used, confirm behaviour when the /decide endpoint is unreachable — you want a deterministic default, not an exception.
Sequencing.
Analytics contract and PostHog-backed implementation; make it no-op-safe in local and testing.ShouldQueue, dedicated queue, tries/backoff) with a hard timeout.Maintenance. Low ongoing code maintenance — the SDK surface is small and stable, and MIT licensing removes legal friction. The real maintenance burden is schema and taxonomy governance: event names and property keys drift without a reviewer, and that drift is what makes dashboards untrustworthy. Pin the version, subscribe to releases, and schedule an upgrade review each quarter. Given the metadata anomalies in the intake, treat the "official SDK" status as a claim to verify rather than a settled fact.
Support. Upstream is PostHog itself, so support quality tracks your commercial relationship: paid plans get a real support channel, free/self-hosted users get docs and community. Internal support risk is concentrated in one or two engineers who understand the wrapper and taxonomy — document it or it becomes tribal knowledge.
Scaling. The SDK itself scales fine; your usage pattern is what scales badly. Unbatched, per-request capture will become both a latency and a cost problem as traffic grows. Mitigations: dedicated queue with worker headroom, event batching where the API allows it, sampling on high-volume events (page views, list loads), and excluding non-business-critical events from synchronous paths entirely. Watch queue depth as the primary capacity signal; a PostHog outage should back up the queue, not the request path.
Failure modes. Ranked by likely damage: (1) synchronous capture adding tail latency to critical flows; (2) event loss during PostHog incidents going undetected because exceptions are swallowed; (3) PII leakage through unvalidated property payloads; (4) flag evaluation failing closed and disabling a feature for all users, or failing open and exposing an unfinished feature; (5) double-counting after a migration or after adding server-side capture to an app that already had client-side capture. Each needs an explicit, written policy — the SDK will not make these decisions for you.
Ramp-up. For a Laravel engineer new to PostHog, roughly one to two days to a working, queued, tested integration, plus a day for the wrapper and test fakes. Feature flags add another one to two days once caching, fallback defaults, and rollout controls are handled properly. The larger cost is product-side: defining the event taxonomy and agreeing on success metrics typically takes longer than the engineering and is the actual determinant of whether this package delivers value. At an opportunity score of ~2.2, this is a low-glamour, low-risk utility dependency — worth adopting, not worth architecting around.
How can I help you explore Laravel packages today?