temperbit / larahog
The Laravel-native PostHog experience.
Fund package maintenance!
Requires
- php: ^8.3
- illuminate/contracts: ^11.0||^12.0|^13.0
- posthog/posthog-php: ^4.2
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- larastan/larastan: ^3.0
- laravel/pennant: ^1.0
- laravel/pint: ^1.14
- nunomaduro/collision: ^8.8
- orchestra/testbench: ^11.0.0|^10.0.0||^9.0.0
- pestphp/pest: ^4.0
- pestphp/pest-plugin-arch: ^4.0
- pestphp/pest-plugin-laravel: ^4.0
- phpstan/extension-installer: ^1.4
- phpstan/phpstan-deprecation-rules: ^2.0
- phpstan/phpstan-phpunit: ^2.0
This package is auto-updated.
Last update: 2026-08-15 00:26:04 UTC
README
The Laravel-native PostHog experience. LaraHog wraps the PostHog PHP SDK into a first-class Laravel package with multi-connection support, queue-based dispatch, and Octane compatibility out of the box.
Requirements
- PHP 8.3+
- Laravel 11, 12, or 13
Support us
We invest a lot of resources into creating awesome software. You can support us by sponsoring us on GitHub.
Installation
composer require temperbit/larahog
Publish the config file:
php artisan vendor:publish --tag="larahog-config"
Add your PostHog project token to .env:
POSTHOG_PROJECT_TOKEN=phc_your_project_token
Configuration
The published config file will be at config/larahog.php.
| Variable | Default | Description |
|---|---|---|
POSTHOG_CONNECTION |
default |
Default connection name |
POSTHOG_ENABLED |
true |
Enable/disable the default connection |
POSTHOG_PROJECT_TOKEN |
"" |
Your PostHog project API key |
POSTHOG_HOST |
https://us.i.posthog.com |
PostHog instance URL |
POSTHOG_DISPATCH_MODE |
sync |
sync or queue |
POSTHOG_QUEUE_CONNECTION |
null |
Laravel queue connection (when using queue mode) |
POSTHOG_QUEUE_NAME |
default |
Laravel queue name (when using queue mode) |
Multi-connection support
You can define multiple PostHog connections for different projects:
// config/larahog.php 'connections' => [ 'default' => [ 'project_token' => env('POSTHOG_PROJECT_TOKEN'), // ... ], 'marketing' => [ 'project_token' => env('POSTHOG_MARKETING_TOKEN'), // ... ], ],
Then target a specific connection:
LaraHog::connection('marketing')->capture('user-123', 'campaign_clicked');
Usage
Capturing events
use TemperBit\LaraHog\Facades\LaraHog; // Basic event LaraHog::capture('user-123', 'page_viewed'); // With properties LaraHog::capture('user-123', 'purchase_completed', [ 'amount' => 49.99, 'currency' => 'USD', ]); // With group association LaraHog::capture('user-123', 'report_exported', [], [ 'company' => 'company-456', ]); // Anonymous event LaraHog::capture(null, 'landing_page_viewed'); // Historical event time (DateTimeInterface, Unix timestamp, or ISO 8601 string) LaraHog::capture( 'user-123', 'package_downloaded', timestamp: $downloadedAt, );
LaraHog records the timestamp when each operation is requested, before any queue delay. Pass the optional timestamp argument to capture, captureException, identify, alias, or groupIdentify when importing historical events.
Capturing batches
Use captureBatch to queue multiple events for one PostHog batch. Set historicalMigration when backfilling old events so LaraHog sends the batch through PostHog's historical ingestion pipeline.
LaraHog::captureBatch([ [ 'distinctId' => 'user-123', 'event' => 'package_downloaded', 'properties' => ['package' => 'agent'], 'timestamp' => $firstDownloadAt, ], [ 'distinctId' => 'user-456', 'event' => 'package_downloaded', 'properties' => ['package' => 'sensor'], 'timestamp' => $secondDownloadAt, ], ], historicalMigration: true);
Historical batches are isolated from buffered live events and carry PostHog's top-level historical_migration flag.
Identifying users
LaraHog::identify('user-123', [ 'name' => 'Jane Doe', 'email' => 'jane@example.com', 'plan' => 'enterprise', ]);
Use identifyBatch to identify multiple users through one PostHog batch request:
LaraHog::identifyBatch([ ['distinctId' => 'user-123', 'properties' => ['name' => 'Jane Doe']], ['distinctId' => 'user-456', 'properties' => ['name' => 'John Doe']], ]);
Aliasing identities
LaraHog::alias('user-123', 'anonymous-session-abc');
Group identities
LaraHog::groupIdentify('company', 'company-456', [ 'name' => 'Acme Corp', 'industry' => 'SaaS', ]);
Use groupIdentifyBatch to identify multiple groups through one PostHog batch request:
LaraHog::groupIdentifyBatch([ ['groupType' => 'company', 'groupKey' => 'company-456', 'properties' => ['name' => 'Acme Corp']], ['groupType' => 'company', 'groupKey' => 'company-789', 'properties' => ['name' => 'Globex Corp']], ]);
Flushing
LaraHog automatically flushes pending events when the application terminates. You can also flush manually:
LaraHog::flush(); // Flush the default connection LaraHog::flushAll(); // Flush all connections
Checking status
if (LaraHog::isEnabled()) { // ... }
Dispatch Modes
Sync (default)
Events are buffered in memory by the PostHog SDK and sent in batches at the end of the request lifecycle. This is the simplest setup and works well for most applications.
POSTHOG_DISPATCH_MODE=sync
Queue
Events are dispatched to a Laravel queue for asynchronous processing. This moves PostHog API calls out of the request path entirely.
POSTHOG_DISPATCH_MODE=queue POSTHOG_QUEUE_CONNECTION=redis POSTHOG_QUEUE_NAME=analytics
Octane Compatibility
LaraHog uses a PostHog\Client instance (not the static PostHog::init() method), so each request gets a clean state. Multi-connection support is handled through the LaraHogManager singleton, which lazily resolves connections. This design is safe to use with Laravel Octane.
Artisan Commands
larahog:status
Displays the current configuration and tests connectivity to PostHog:
php artisan larahog:status php artisan larahog:status --connection=marketing
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.