mike-bronner/laravel-mixpanel
mike-bronner/laravel-mixpanel is a Laravel package that provides a clean wrapper around the Mixpanel PHP SDK. It lets you track events, identify users, set people properties, and send analytics data from your Laravel app with simple configuration and a friendly facade.
Upgrade/install
composer require genealabs/laravel-mixpanel:^13.0
13.0.0 adds Laravel 13 and PHP 8.5 support, so also confirm your app's php constraint and run composer why-not before upgrading on older runtimes.
Publish the new config file first. 13.0.0 moved Mixpanel configuration into a dedicated, publishable config file. Publish it and diff it against whatever config you had before (previously merged/embedded config, or values you'd stuffed into config/services.php):
php artisan vendor:publish --tag=mixpanel-config
php artisan config:clear
Set credentials in .env — at minimum your project token (plus region/residency and consumer options if you use them):
MIXPANEL_TOKEN=...
MIXPANEL_ENABLED=true
First use case — server-side event tracking. Fire one event from a controller, listener, or tinker to confirm wiring:
use Mixpanel;
Mixpanel::track('App Installed', ['version' => app()->version()]);
Where to look first: config/mixpanel.php for the token, region, consumer, and enabled flags; your User (or other subject) model if you want a custom distinct ID via getMixpanelKey(); and your auth/login flow for where you call identify().
Centralize events in listeners, not controllers. Map domain events to tracking calls so business logic stays clean:
// app/Listeners/TrackCheckoutCompleted.php
public function handle(OrderPaid $event): void
{
Mixpanel::track('Checkout Completed', [
'order_id' => $event->order->id,
'revenue' => $event->order->total,
'currency' => $event->order->currency,
]);
}
Keep event names and property keys in constants/enums — Mixpanel queries break silently when a property is spelled differently across call sites.
Identify once, then rely on the distinct ID. Call Mixpanel::identify(...) (and people->set(...) for profile properties) at login or account creation, and make sure the ID matches what the JS SDK sends on the client.
Custom distinct ID via getMixpanelKey() (new in 13.0.0). Implement it on your subject model to control the Mixpanel distinct ID instead of defaulting to getKey()/the auth ID:
class User extends Authenticatable
{
public function getMixpanelKey(): string|int
{
return $this->uuid; // or a tenant-scoped ID, email, etc.
}
}
This is the pattern to reach for when your internal primary key changes between databases, when you need an anonymized ID, or when you want client and server to agree on identity.
Queue the calls. Tracking is a network round-trip. Dispatch a job / ShouldQueue listener (after commit, via afterCommit) so checkout flows don't depend on Mixpanel availability.
Test seam. Disable the integration in tests (MIXPANEL_ENABLED=false or the config flag) and assert on your own domain events/queued jobs rather than on the Mixpanel client.
Bulk vs streaming. Use the track/identify calls for live behavior and the package's import path for backfills; don't loop track over thousands of rows in a request.
config/services.php, or an old published config, may simply be ignored — which looks like "tracking stopped working" rather than an error. Republish, diff, and config:clear on deploy.getMixpanelKey() semantics: return a stable, non-empty scalar. Returning null/'' or implementing the method on the wrong model (e.g. the Auth user when you're tracking a Customer) silently falls back or breaks identification. The method only helps if the package resolves it from the subject you're actually tracking.alias when migrating existing users.How can I help you explore Laravel packages today?