Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Analytics Php Laravel Package

segmentio/analytics-php

Official PHP client for Segment's analytics API. Track events, identify users, record page views, group accounts, and alias identities from PHP applications, with batching and error handling, routing data to hundreds of analytics and marketing destinations.

View on GitHub
Deep Wiki
Context7

Getting Started

Install with Composer:

composer require segmentio/analytics-php

There are two entry points; use whichever the installed version exposes. Recent releases expose Segment\Client; the older static facade is still widely documented:

// Object-oriented client (preferred where available)
$client = new \Segment\Client('YOUR_WRITE_KEY', ['debug' => true]);

// Classic static facade
\Segment\Analytics::init('YOUR_WRITE_KEY', ['debug' => true]);

Send your first event and flush:

$client->identify([
    'userId' => 'user_42',
    'traits' => ['email' => '[email protected]', 'plan' => 'pro'],
]);

$client->track([
    'userId' => 'user_42',
    'event'  => 'Order Completed',
    'properties' => ['orderId' => 'o_123', 'revenue' => 49.00],
]);

$client->flush(); // force pending messages out

Look first at:

  1. README.md for the message method signatures.
  2. lib/Segment/Client.php and lib/Segment/Analytics.php to confirm which API surface your installed version has.
  3. lib/Segment/Consumer/ — the consumer choice is the single biggest behavioural switch (Socket is the default, Curl, File, ForkCurl also ship).
  4. test/ — the file consumer is used heavily there and is the fastest way to understand payload shape.

First useful use case: identify-on-login, track key funnel events (signup, checkout, subscription), and flush() at the end of the request. Do not try to model analytics inside your domain layer on day one; start with a small application service that wraps Segment\Client and call it from controllers/listeners.

Implementation Patterns

Wrap the client, don’t call it everywhere. Register one instance in your container (or a small wrapper AnalyticsService) and inject it. This gives you a single place to add common context, enforce userId/anonymousId, and switch consumers in tests.

Populate default context once. Server-side calls should carry useful context (IP, user agent, app version, environment) so destinations can segment later:

$client->track([
    'userId' => $user->id,
    'event' => 'Report Exported',
    'properties' => ['format' => 'pdf'],
    'context' => [
        'ip' => $request->ip(),
        'userAgent' => $request->userAgent(),
        'app' => ['name' => 'billing', 'version' => '2.4.1'],
        'locale' => app()->getLocale(),
    ],
]);

Bake this into your wrapper so callers only pass business data.

Use identify at authentication boundaries, track for behaviour. Typical flow: identify in your login listener with durable traits (email, plan, company), track in domain/application events, group for B2B account membership, alias on account merge or anonymous-to-known transitions.

Anonymous → known transitions. For pre-signup activity, generate and persist an anonymousId, send it on track/page, then call alias(['previousId' => $anonId, 'userId' => $newUserId]) and identify once the user registers. Reuse the same anonymousId across requests — usually from a cookie or session.

Routing with integrations. Rather than creating separate clients per destination, send one event and toggle destinations:

$client->track([
    'userId' => $user->id,
    'event' => 'Internal Debug Ping',
    'properties' => ['...' => '...'],
    'integrations' => ['All' => false, 'Amplitude' => true],
]);

This is the clean way to keep noisy server events out of marketing tools while still feeding product analytics.

Queue decoupling. The PHP client is synchronous by default (it opens connections on flush). For high-traffic endpoints, push a job and call Segment from a queue worker. This keeps request latency predictable and lets you retry. Pair this with periodic flush() in the worker — see Gotchas.

Testing pattern. Swap in the file consumer so tests can assert on emitted JSON lines instead of mocking HTTP:

$client = new \Segment\Client('test-key', [
    'consumer' => 'file',
    'filename' => '/tmp/segment-test.log',
]);

Or mock your own AnalyticsService interface; asserting on raw Segment payloads in every test becomes brittle.

Laravel integration. Bind Segment\Client as a singleton in a service provider with config-driven key/options, then inject your wrapper into listeners. For Laravel Octane or Swoole, treat the client as long-lived and flush explicitly (again, see Gotchas).

Gotchas and Tips

Events are buffered; short-lived requests need flush(). The default Socket consumer queues messages in memory. If your PHP process ends without flushing (or the shutdown handler is skipped by exit/fatal errors/fastcgi_finish_request ordering), events are silently lost. In web requests, flushing at the end of the request is usually fine; in CLI scripts and queue workers, call flush() deliberately and often.

Long-running processes leak memory and lose data without flushing. Under Octane, RoadRunner, or a queue worker, the client instance persists. Either flush after each job/batch or recreate the client per unit of work. Left alone, the queue grows unbounded.

Failures are silent unless debug is on. By default the library swallows send errors to avoid breaking your app. Enable ['debug' => true] in local/staging, and wrap a health check or log in your wrapper if analytics correctness matters. In production, consider logging flush failures from your wrapper rather than globally.

Consumer choice has real consequences. Socket writes directly to Segment over TLS (or plaintext if ssl is disabled); it can add latency on flush and depends on OpenSSL being available. Curl is often more predictable behind proxies and load balancers. ForkCurl uses pcntl_fork — typically unavailable or unwise in FPM/containers. Confirm your target environment before changing consumers.

Set a timeout. Network flushes should never hold your request indefinitely. Configure timeout on the client and keep it short in the request path; do the heavy lifting in a queue if you need retries.

userId vs anonymousId. Segment accepts either, but sending neither means destinations can’t attribute the event. Enforce one in your wrapper — a small guard that throws in non-production is worth the friction.

Context auto-population differs from the browser. The PHP library adds library info and limited server context; it does not know the browser IP behind a proxy unless you pass it. If you run behind Nginx/Cloudflare/ALB, set trusted proxies so $request->ip() is meaningful, otherwise every user looks like your load balancer.

Global static state bites in tests. Segment\Analytics::init() sets process-wide state; one test’s key/consumer leaks into the next. Prefer the Client object, or reset in tearDown(). Parallel test runners can also collide on a shared file-consumer filename — use unique temp paths.

Timestamps and ordering. Server clocks drift. If you replay historical events, pass an explicit timestamp (ISO 8601 or DateTime) so Segment doesn’t stamp them with “now”. Same for backfills and migrations.

Idempotency. Supply your own messageId when retrying after ambiguous failures; otherwise a retry looks like a new event and inflates counts. Derive it from your domain event ID.

Version pinning matters here. The package has undergone API shifts (static Analytics vs Client, additions like the Curl consumer). Pin a minor version and confirm the method signatures against the vendored source, not just internet examples — a lot of blog posts target old releases.

Extension point: custom consumers. If you need to batch into a queue, mirror to a warehouse, or assert in tests, implement a consumer that matches the shipped interface and pass it by name/class. That is the supported escape hatch; subclassing the client is not.

Don’t send PII you can’t delete. Traits and properties flow into third parties. Avoid raw passwords, tokens, full card numbers, and health data. Keep a short allowlist of trait keys in your wrapper so a well-meaning developer can’t accidentally ship a full user model.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core