Laravel Posthog
#Laravel PostHog
A PHP/Laravel client for PostHog. Capture events, batch ingestion, identify people, evaluate feature flags and read back persons, insights, session recordings and HogQL queries — through a simple, typed API built on Laravel's Http client. Works with PostHog Cloud (US/EU) and self-hosted instances.
#Features
- Event capture: single events and batched ingestion
- Person identification:
$identifyand$create_aliashelpers over the capture endpoint - Feature flags: read every flag for a person, a single flag value (including multivariate variants), or a simple boolean check
- Persons: look people up by
distinct_id - HogQL: run SQL-like queries against your event data
- Insights and session recordings: list them from the project API
- Handles PostHog's two auth models for you — the public project API key in the payload for ingestion, the personal API key as a Bearer token for reads
- Throws
PostHogException(with the original API error body) on any non-2xx response
#Installation
You can install the package via composer:
composer require jeffersongoncalves/laravel-posthog
Publish the config file:
php artisan vendor:publish --tag=posthog-config
Then set your credentials:
POSTHOG_HOST=https://us.i.posthog.com POSTHOG_PROJECT_API_KEY=phc_your_project_api_key POSTHOG_PERSONAL_API_KEY=phx_your_personal_api_key POSTHOG_PROJECT_ID=12345
POSTHOG_PROJECT_API_KEY is the public write-only key and is all you need for capture, batch and feature flags. POSTHOG_PERSONAL_API_KEY plus POSTHOG_PROJECT_ID are only required for the read endpoints (persons, HogQL, insights, session recordings).
#Configuration
// config/posthog.php return [ 'host' => env('POSTHOG_HOST', 'https://app.posthog.com'), 'project_api_key' => env('POSTHOG_PROJECT_API_KEY', ''), 'personal_api_key' => env('POSTHOG_PERSONAL_API_KEY', ''), 'project_id' => env('POSTHOG_PROJECT_ID', ''), 'timeout' => env('POSTHOG_TIMEOUT', 10), ];
#Usage
The package is resolved via the PostHog facade or by injecting JeffersonGoncalves\PostHog\PostHog.
#Capturing events
use JeffersonGoncalves\PostHog\Facades\PostHog; PostHog::capture('signup_completed', 'user_123', [ 'plan' => 'pro', '$current_url' => 'https://example.com/signup', ]);
#Batching events
PostHog::batch([ ['event' => 'pageview', 'distinct_id' => 'user_1'], ['event' => 'signup', 'distinct_id' => 'user_2'], ]);
#Identifying people
PostHog::identify('user_123', [ 'email' => 'user@example.com', 'plan' => 'pro', ]); // Merge an anonymous session into an identified person PostHog::alias('user_123', 'anon_abc');
#Feature flags
// Every flag evaluated for this person $flags = PostHog::featureFlags('user_123'); // A single flag: false when off, true when on, the variant key when multivariate $variant = PostHog::featureFlag('new-pricing', 'user_123'); // Simple boolean check (a variant counts as enabled) if (PostHog::isFeatureEnabled('new-pricing', 'user_123')) { // Show new pricing }
Group-based flags are supported by passing the groups map:
PostHog::isFeatureEnabled('beta-dashboard', 'user_123', ['company' => 'acme-inc']);
#Persons
$persons = PostHog::persons('user_123');
#HogQL queries
$result = PostHog::query( 'SELECT event, count() FROM events WHERE timestamp > now() - interval 7 day GROUP BY event ORDER BY count() DESC LIMIT 10' );
#Insights and session recordings
$insights = PostHog::insights(); $recordings = PostHog::sessionRecordings(['limit' => 20]);
#Error handling
Any non-2xx API response throws JeffersonGoncalves\PostHog\Exceptions\PostHogException, which exposes the decoded error body:
use JeffersonGoncalves\PostHog\Exceptions\PostHogException; try { PostHog::persons('user_123'); } catch (PostHogException $e) { logger()->error($e->getMessage(), $e->errorBody()); }
#Testing
composer test
#Changelog
Please see CHANGELOG for more information on what has changed recently.
#Contributing
Please see CONTRIBUTING for details.
#Security Vulnerabilities
Please review our security policy on how to report security vulnerabilities.
#Credits
#License
The MIT License (MIT). Please see License File for more information.