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

Laravel Segment Laravel Package

slashequip/laravel-segment

slashequip/laravel-segment provides a simple Laravel integration for Segment analytics, with a facade and helpers for identifying users and tracking events server-side, plus configuration for your Segment write key and client-side snippet.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package with Composer alongside your existing Laravel app:

composer require slashequip/laravel-segment

Publish the config so you can see what knobs are exposed (write key, endpoint, queueing, etc.):

php artisan vendor:publish --provider="Slashequip\LaravelSegment\SegmentServiceProvider"

Set at least your Segment write key in .env — this is the source write key, not a personal API token:

SEGMENT_WRITE_KEY=your_write_key

Then clear config if you're in a cached environment:

php artisan config:clear

Where to look first

  1. config/segment.php — read it end-to-end. It tells you whether the package queues, how it resolves user identity, and what HTTP client/transport it uses.
  2. The package's SegmentServiceProvider — it reveals the binding name behind the facade and any middleware or macro registrations.
  3. The facade alias in config/app.php. Most day-to-day usage goes through it.

Your first use case

The fastest meaningful win is instrumenting a server-side track call for a critical conversion event (signup, subscription started, checkout completed). Resolve the facade and fire the event:

use Slashequip\LaravelSegment\Facades\Segment;

Segment::track('User Signed Up', [
    'plan' => $user->plan,
    'source' => 'web',
], [
    'userId' => (string) $user->id,
]);

If the event shows up in Segment's Debugger within a few seconds, the wiring is correct and you can move on to identifying users and building reusable patterns around it.


Implementation Patterns

1. Identify once per request, track many times

Segment works best when identify provides context and track calls reference a userId. The least noisy approach is a small middleware that identifies the authenticated user after auth resolves:

class IdentifyWithSegment
{
    public function handle($request, Closure $next)
    {
        if ($user = $request->user()) {
            Segment::identify((string) $user->id, [
                'email' => $user->email,
                'name' => $user->name,
                'plan' => $user->plan,
                'created_at' => $user->created_at->toIso8601String(),
            ]);
        }

        return $next($request);
    }
}

Register it in the web group so every authenticated request carries identity. Keep the trait payload stable — changing trait keys frequently makes downstream warehouse schemas angry.

2. Wrap calls in an application analytics service

Do not sprinkle Segment::track(...) through controllers. Introduce a thin domain service so event names and shapes live in one place:

class Analytics
{
    public function __construct(private SegmentClient $segment) {}

    public function orderPlaced(Order $order): void
    {
        $this->segment->track('Order Placed', [
            'order_id' => $order->id,
            'revenue' => $order->total_cents,
            'currency' => $order->currency,
            'product_count' => $order->items()->count(),
        ], ['userId' => (string) $order->user_id]);
    }
}

This gives you a single file to audit for PII, a single place to add consent checks, and a trivial seam for tests.

3. Model events → domain analytics

For CRUD-heavy apps, hooking domain events to a listener is the cleanest pattern:

// app/Providers/EventServiceProvider.php
protected $listen = [
    \App\Events\SubscriptionStarted::class => [
        \App\Listeners\TrackSubscriptionStarted::class,
    ],
];

The listener calls Analytics, not Segment directly. This keeps transport (Segment) decoupled from domain events — if you ever swap to a different CDP, only the Analytics service changes.

4. Queue the calls, don't block the request

Segment's API is remote HTTP. Even at ~100ms, it will noticeably lengthen p95 request latency under load. Always:

  • Enable the package's queued/job mode if it exposes one (check queue_events/queue in config/segment.php).
  • Or wrap the call in a job and dispatch it:
dispatch(new TrackSegmentEvent('Order Placed', $properties, $options))
    ->onQueue('analytics');

Run a dedicated analytics queue worker with an aggressive concurrency setting — these jobs are I/O-bound and short.

5. Enrich context centrally

Instead of passing ip, userAgent, locale, app_version on every call, wrap the client in a decorator that merges a default context:

class SegmentContextEnricher
{
    public function track(string $event, array $props, array $options = []): void
    {
        $options['context'] = array_merge($options['context'] ?? [], [
            'ip' => request()->ip(),
            'userAgent' => request()->userAgent(),
            'locale' => app()->getLocale(),
            'app_version' => config('app.version'),
            'environment' => app()->environment(),
        ]);

        $this->inner->track($event, $props, $options);
    }
}

Bind this in the container and inject it everywhere instead of the raw facade.

6. Test with a fake, not the network

Never let tests hit Segment. Two proven approaches:

  • Bind a fake implementation of your Analytics contract in the container.
  • Or use the package's swap/fake facility if it ships one:
Segment::shouldReceive('track')->once()->with('Order Placed', Mockery::any(), Mockery::any());

Even better: assert on your Analytics contract ($analytics->assertTracked('Order Placed')) and keep Segment out of your test surface entirely.

7. Server-side + client-side split

Use the package for authoritative server events (payments, entitlement changes) and use analytics.js client-side for UI intent. Do not double-track the same event from both sides — Segment will fire two events, and your funnels will be wrong. A good rule: if the server is the source of truth for the fact, track server-side; if it's a UI interaction, track client-side.


Gotchas and Tips

  • Write key vs. API key. The config expects the source write key (used by client/SDKs), not a personal API token. Mixing them up produces 401s you'll spend an hour debugging.
  • identify() before track() matters. If you fire track without userId or anonymousId, Segment drops or fragments the event depending on your destination config. Always pass at least one identity key in the options array.
  • Queue it or pay for it. Synchronous track calls will show up in your APM traces as outbound HTTP. If you see them adding latency, that's a config flag, not a code change — check config/segment.php for a queue/batch option first.
  • Consent and GDPR. Segment will happily forward PII to destinations you're not authorized to send it to in that region. Gate all tracking behind a consent check ($user->hasAnalyticsConsent() or a setting), and be strict about never sending email/phone in track properties — those belong in identify traits.
  • Config cache is a footgun. If events stop appearing after deploy, php artisan config:cache almost certainly ran and cached a stale/missing SEGMENT_WRITE_KEY. Add the env var to your deploy checklist.
  • Local dev noise. Set SEGMENT_ENABLED=false (or the package's equivalent) in .env.testing and .env.local. Don't rely on your dev write key pointing to a sandbox — someone always forgets.
  • Event name conventions drift. Decide on Title Case vs snake_case on day one and enforce it in your Analytics service. Segment allows both, but your dashboards won't thank you for the mixture.
  • Debugging silently failing events. Segment's HTTP API returns 200 even when a destination rejects the event (it accepts into the pipeline). Use the Segment Debugger, not your app logs, to confirm delivery. Enable the package's debug/logging option to at least catch transport-level errors.
  • Extension point: the HTTP client. If you need retries, custom timeouts, or a proxy, the right place is the package's underlying segmentio/analytics-php client or the transport binding — not wrapping each call in try/catch. Bind your configured client in a service provider rather than forking the package.
  • Ordering isn't guaranteed. Queued events can arrive out of order. If a downstream tool needs identify before an track, either batch them or include the relevant traits in every track call's traits. Don't assume the middleware ran first for background jobs.
  • Batching is a double-edged sword. Batch endpoints reduce HTTP overhead but delay delivery and complicate debugging individual events. Only batch for high-volume, non-critical events; keep conversion events immediate.
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.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin