Laravel Package
Laravel package with service providers and middleware
Laravel Package
The entrolytics-laravel-middleware package provides a comprehensive Laravel package for analytics tracking with service providers, middleware, facades, and seamless Laravel integration.
Installation
composer require entrolytics/laravel-middlewareQuick Start
Install Package
composer require entrolytics/laravel-middlewarePublish Configuration
php artisan vendor:publish --provider="Entrolytics\Laravel\EntrolyticsServiceProvider"Configure Environment
# .env
ENTROLYTICS_WEBSITE_ID=your-website-id
ENTROLYTICS_API_KEY=your-api-key
ENTROLYTICS_HOST=https://entrolytics.devUse in Controller
<?php
namespace App\Http\Controllers;
use Entrolytics\Facades\Entrolytics;
use Illuminate\Http\Request;
class UserController extends Controller
{
public function show($id)
{
$user = User::findOrFail($id);
// Track page view
Entrolytics::page('user_profile', [
'user_id' => $user->id,
'user_role' => $user->role
]);
return view('users.show', compact('user'));
}
public function store(Request $request)
{
// Track event
Entrolytics::track('user_creation_attempt', [
'email' => $request->email,
'source' => $request->input('source', 'web')
]);
$user = User::create($request->validated());
// Track success
Entrolytics::track('user_created', [
'user_id' => $user->id,
'email' => $user->email
]);
return redirect()->route('users.show', $user);
}
}Configuration
Configuration File
// config/entrolytics.php
return [
/*
|--------------------------------------------------------------------------
| Website ID
|--------------------------------------------------------------------------
|
| Your Entrolytics website ID. This is required for tracking.
|
*/
'website_id' => env('ENTROLYTICS_WEBSITE_ID'),
/*
|--------------------------------------------------------------------------
| API Key
|--------------------------------------------------------------------------
|
| Your Entrolytics API key. Optional, used for enhanced features.
|
*/
'api_key' => env('ENTROLYTICS_API_KEY'),
/*
|--------------------------------------------------------------------------
| Host
|--------------------------------------------------------------------------
|
| The Entrolytics API host URL.
|
*/
'host' => env('ENTROLYTICS_HOST', 'https://entrolytics.dev'),
/*
|--------------------------------------------------------------------------
| Auto Track
|--------------------------------------------------------------------------
|
| Automatically track HTTP requests.
|
*/
'auto_track' => env('ENTROLYTICS_AUTO_TRACK', true),
/*
|--------------------------------------------------------------------------
| Track Errors
|--------------------------------------------------------------------------
|
| Automatically track exceptions and errors.
|
*/
'track_errors' => env('ENTROLYTICS_TRACK_ERRORS', true),
/*
|--------------------------------------------------------------------------
| Exclude Paths
|--------------------------------------------------------------------------
|
| Paths to exclude from automatic tracking.
|
*/
'exclude_paths' => [
'health',
'metrics',
'nova-api/*',
'telescope*',
],
/*
|--------------------------------------------------------------------------
| Include Headers
|--------------------------------------------------------------------------
|
| HTTP headers to include in tracking data.
|
*/
'include_headers' => [
'User-Agent',
'X-Forwarded-For',
'X-Real-IP',
'Referer',
],
/*
|--------------------------------------------------------------------------
| User Identification
|--------------------------------------------------------------------------
|
| Automatically identify authenticated users.
|
*/
'identify_users' => env('ENTROLYTICS_IDENTIFY_USERS', true),
/*
|--------------------------------------------------------------------------
| Queue Tracking
|--------------------------------------------------------------------------
|
| Track queued job events.
|
*/
'track_queue' => env('ENTROLYTICS_TRACK_QUEUE', true),
/*
|--------------------------------------------------------------------------
| Debug Mode
|--------------------------------------------------------------------------
|
| Enable debug logging for development.
|
*/
'debug' => env('ENTROLYTICS_DEBUG', env('APP_DEBUG', false)),
];Service Provider Registration
// config/app.php
'providers' => [
// ... other providers
/*
* Package Service Providers...
*/
Entrolytics\Laravel\EntrolyticsServiceProvider::class,
],
/*
|--------------------------------------------------------------------------
| Class Aliases
|--------------------------------------------------------------------------
*/
'aliases' => [
// ... other aliases
'Entrolytics' => Entrolytics\Laravel\Facades\Entrolytics::class,
],API Reference
Facade Methods
use Entrolytics\Facades\Entrolytics;
// Track custom events
Entrolytics::track(string $event, array $properties = []): void
// Track page views
Entrolytics::page(string $url, array $properties = []): void
// Identify users
Entrolytics::identify(string $userId, array $traits = []): void
// Set user properties
Entrolytics::setUserProperties(array $properties): void
// Track multiple events
Entrolytics::trackBatch(array $events): void
// Flush pending events
Entrolytics::flush(): void
// Enable/disable tracking
Entrolytics::setEnabled(bool $enabled): void
// Check if tracking is enabled
Entrolytics::isEnabled(): bool
// Get configuration
Entrolytics::getConfig(): arrayHelper Functions
// Global helper functions
entrolytics_track(string $event, array $properties = []): void
entrolytics_page(string $url, array $properties = []): void
entrolytics_identify(string $userId, array $traits = []): void
entrolytics_set_properties(array $properties): voidRequest Macro
// Available on Illuminate\Http\Request
$request->entrolytics()->track($event, $properties);
$request->entrolytics()->identify($userId, $traits);
$request->entrolytics()->page($url, $properties);Advanced Usage
Middleware Integration
// app/Http/Kernel.php
protected $middleware = [
// ... other middleware
\Entrolytics\Laravel\Middleware\TrackRequests::class,
];
protected $middlewareGroups = [
'web' => [
// ... other middleware
\Entrolytics\Laravel\Middleware\IdentifyUsers::class,
],
'api' => [
// ... other middleware
\Entrolytics\Laravel\Middleware\TrackApiRequests::class,
],
];Custom Middleware
<?php
namespace App\Http\Middleware;
use Closure;
use Entrolytics\Facades\Entrolytics;
use Illuminate\Http\Request;
class CustomAnalytics
{
public function handle(Request $request, Closure $next)
{
$response = $next($request);
// Track API version
if ($apiVersion = $request->header('API-Version')) {
Entrolytics::track('api_request', [
'version' => $apiVersion,
'method' => $request->method(),
'endpoint' => $request->path(),
'status' => $response->getStatusCode()
]);
}
// Track authenticated users with custom properties
if ($request->user()) {
Entrolytics::identify($request->user()->id, [
'email' => $request->user()->email,
'role' => $request->user()->role,
'subscription' => $request->user()->subscription?->type,
'last_login' => $request->user()->last_login_at->toISOString()
]);
}
return $response;
}
}Controller Integration
<?php
namespace App\Http\Controllers;
use Entrolytics\Facades\Entrolytics;
use Illuminate\Http\Request;
class AnalyticsController extends Controller
{
public function dashboard()
{
// Track dashboard access
Entrolytics::page('dashboard', [
'user_role' => auth()->user()->role,
'has_notifications' => auth()->user()->unreadNotifications()->count() > 0,
'last_login' => auth()->user()->last_login_at->diffInDays(now())
]);
return view('dashboard');
}
public function purchase(Request $request)
{
$product = Product::findOrFail($request->product_id);
// Track purchase attempt
Entrolytics::track('purchase_attempt', [
'product_id' => $product->id,
'product_name' => $product->name,
'price' => $product->price,
'currency' => $product->currency,
'payment_method' => $request->payment_method
]);
try {
$order = Order::create([
'user_id' => auth()->id(),
'product_id' => $product->id,
'amount' => $product->price,
// ... other fields
]);
// Track successful purchase
Entrolytics::track('purchase_completed', [
'order_id' => $order->id,
'product_id' => $product->id,
'amount' => $order->amount,
'currency' => $order->currency,
'payment_method' => $request->payment_method
]);
// Update user properties
Entrolytics::setUserProperties([
'total_purchases' => auth()->user()->orders()->count(),
'total_spent' => auth()->user()->orders()->sum('amount'),
'last_purchase' => now()->toISOString()
]);
return redirect()->route('orders.show', $order);
} catch (\Exception $e) {
// Track purchase failure
Entrolytics::track('purchase_failed', [
'product_id' => $product->id,
'error' => $e->getMessage(),
'error_type' => get_class($e),
'payment_method' => $request->payment_method
]);
throw $e;
}
}
}Model Events
<?php
namespace App\Providers;
use App\Models\User;
use Illuminate\Support\Facades\Event;
use Entrolytics\Facades\Entrolytics;
use Illuminate\Auth\Events\Login;
use Illuminate\Auth\Events\Logout;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
// User authentication events
Event::listen(Login::class, function ($event) {
Entrolytics::identify($event->user->id, [
'email' => $event->user->email,
'name' => $event->user->name,
'role' => $event->user->role
]);
Entrolytics::track('login', [
'method' => 'web',
'ip_address' => request()->ip(),
'user_agent' => request()->userAgent()
]);
});
Event::listen(Logout::class, function ($event) {
Entrolytics::track('logout', [
'method' => 'web',
'session_duration' => session('login_time') ? now()->diffInSeconds(session('login_time')) : null
]);
});
// Model events
User::created(function ($user) {
Entrolytics::track('user_registered', [
'user_id' => $user->id,
'email' => $user->email,
'registration_source' => request()->input('source', 'web')
]);
});
User::updated(function ($user) {
Entrolytics::track('user_updated', [
'user_id' => $user->id,
'changed_fields' => array_keys($user->getDirty())
]);
});
}
}Queue Job Tracking
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Entrolytics\Facades\Entrolytics;
class ProcessAnalytics implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $data;
public function __construct(array $data)
{
$this->data = $data;
}
public function handle()
{
// Track job start
Entrolytics::track('job_started', [
'job_class' => static::class,
'queue' => $this->queue,
'attempt' => $this->attempts()
]);
try {
// Process the data
$result = $this->processData($this->data);
// Track job completion
Entrolytics::track('job_completed', [
'job_class' => static::class,
'result_count' => count($result),
'processing_time' => $this->job->getJob()?->getRuntime()
]);
} catch (\Exception $e) {
// Track job failure
Entrolytics::track('job_failed', [
'job_class' => static::class,
'error' => $e->getMessage(),
'error_type' => get_class($e),
'attempt' => $this->attempts()
]);
throw $e;
}
}
public function failed(\Throwable $exception)
{
Entrolytics::track('job_permanently_failed', [
'job_class' => static::class,
'error' => $exception->getMessage(),
'max_attempts' => $this->tries
]);
}
}Form Request Validation
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Entrolytics\Facades\Entrolytics;
class StoreUserRequest extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users',
'password' => 'required|string|min:8|confirmed',
];
}
protected function failedValidation(\Illuminate\Contracts\Validation\Validator $validator)
{
// Track validation errors
Entrolytics::track('form_validation_failed', [
'form' => 'user_registration',
'errors' => $validator->errors()->toArray(),
'invalid_fields' => array_keys($validator->errors()->toArray())
]);
parent::failedValidation($validator);
}
}Testing
Unit Tests
<?php
namespace Tests\Unit;
use Tests\TestCase;
use Entrolytics\Facades\Entrolytics;
use Entrolytics\Laravel\EntrolyticsManager;
use Illuminate\Foundation\Testing\RefreshDatabase;
class AnalyticsTest extends TestCase
{
use RefreshDatabase;
protected function setUp(): void
{
parent::setUp();
// Mock the analytics client
Entrolytics::fake();
}
public function test_track_event()
{
Entrolytics::track('test_event', ['property' => 'value']);
Entrolytics::assertTracked('test_event', function ($event) {
return $event['properties']['property'] === 'value';
});
}
public function test_identify_user()
{
$user = User::factory()->create();
Entrolytics::identify($user->id, [
'email' => $user->email,
'name' => $user->name
]);
Entrolytics::assertIdentified($user->id, function ($traits) {
return $traits['email'] === $user->email;
});
}
public function test_middleware_tracking()
{
$response = $this->get('/');
$response->assertStatus(200);
// Assert that automatic tracking was called
Entrolytics::assertTracked('page_view');
}
}Feature Tests
<?php
namespace Tests\Feature;
use Tests\TestCase;
use App\Models\User;
use Entrolytics\Facades\Entrolytics;
class UserControllerTest extends TestCase
{
public function test_user_creation_tracks_events()
{
Entrolytics::fake();
$userData = [
'name' => 'John Doe',
'email' => 'john@example.com',
'password' => 'password',
'password_confirmation' => 'password'
];
$response = $this->post('/users', $userData);
$response->assertRedirect();
// Assert events were tracked
Entrolytics::assertTracked('user_creation_attempt');
Entrolytics::assertTracked('user_created');
// Assert user was identified
$user = User::where('email', 'john@example.com')->first();
Entrolytics::assertIdentified($user->id);
}
public function test_form_validation_errors_tracked()
{
Entrolytics::fake();
$invalidData = [
'name' => '',
'email' => 'invalid-email',
'password' => '123'
];
$response = $this->post('/users', $invalidData);
$response->assertSessionHasErrors();
// Assert validation error was tracked
Entrolytics::assertTracked('form_validation_failed', function ($event) {
return isset($event['properties']['errors']);
});
}
}Performance Optimization
Async Tracking
<?php
namespace App\Http\Controllers;
use Entrolytics\Facades\Entrolytics;
use Illuminate\Http\Request;
class PerformanceController extends Controller
{
public function fastEndpoint(Request $request)
{
// Track asynchronously to avoid blocking
dispatch(function () use ($request) {
Entrolytics::track('fast_endpoint_access', [
'path' => $request->path(),
'method' => $request->method()
]);
})->afterResponse();
return response()->json(['status' => 'ok']);
}
}Batching
<?php
namespace App\Services;
use Entrolytics\Facades\Entrolytics;
use Illuminate\Support\Collection;
class AnalyticsBatchService
{
protected $events = [];
protected $batchSize = 50;
public function addEvent(string $event, array $properties = [])
{
$this->events[] = [
'event' => $event,
'properties' => $properties,
'timestamp' => now()->toISOString()
];
if (count($this->events) >= $this->batchSize) {
$this->flush();
}
}
public function flush()
{
if (!empty($this->events)) {
Entrolytics::trackBatch($this->events);
$this->events = [];
}
}
public function __destruct()
{
$this->flush();
}
}Troubleshooting
Best Practices
Migration Guide
From Manual Analytics
// Before - Manual tracking
use Analytics;
class UserController extends Controller
{
public function show($id)
{
Analytics::track('user_view', ['user_id' => $id]);
// ...
}
}
// After - Laravel package
use Entrolytics\Facades\Entrolytics;
class UserController extends Controller
{
public function show($id)
{
Entrolytics::page('user_profile', ['user_id' => $id]);
// ...
}
}From Other Laravel Analytics
// Before - Other package
use OtherAnalytics\Facades\Analytics;
// After - Entrolytics
use Entrolytics\Facades\Entrolytics;
// Update service provider registration
// config/app.php
'providers' => [
// Remove: OtherAnalytics\ServiceProvider::class
Entrolytics\Laravel\EntrolyticsServiceProvider::class,
],Laravel package for Entrolytics - First-party growth analytics for the edge