diff --git a/README.md b/README.md index 3b78ab4..8acb7b5 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,18 @@ Apply the middleware to your web routes by appending it in the `withMiddleware` }) ``` +You can also apply the middleware to specific routes or groups: + +```php +use Pirsch\Http\Middleware\TrackPageview; + +Route::middleware(TrackPageview::class)->group(function () { + Route::get('/', function () { + return view('welcome'); + }); +}); +``` + #### Manually If you want to manually track pageviews instead, you can use the `Pirsch::track()` method. @@ -69,3 +81,74 @@ Pirsch::track( ], ); ``` + +### Filter pages + +You can configure the `TrackPageview` middleware to exclude specific pages from being tracked. + +On a specific rouute, you can exclude pages by adding a `except` property to the middleware class: + +```php +use Pirsch\Http\Middleware\TrackPageview; + +Route::middleware(TrackPageview::class.':url/to/exclude/*')->group(function () { + Route::get('/', function () { + return view('welcome'); + }); +}); +``` + +Multiple urls can be excluded by separating them with a comma: + +```php +use Pirsch\Http\Middleware\TrackPageview; + +Route::middleware(TrackPageview::class.':url/to/exclude/*,url/to/exclude2/*')->group(function () { + Route::get('/', function () { + return view('welcome'); + }); +}); +``` + +To exclude pages globally, you can create a new middleware that extends the `TrackPageview` middleware and add an `except` property: + +```php +namespace App\Http\Middleware; + +use Pirsch\Http\Middleware\TrackPageview as Middleware; + +class TrackPageview extends Middleware +{ + /** + * The URIs that should be excluded from tracking. + * + * @var array + */ + protected array $except = [ + 'url/to/exclude/*', + ]; + + /** + * The Headers that should be excluded from tracking. + * + * @var array + */ + protected array $exceptHeaders = [ + 'X-ExcludedHeader', + ]; +} +``` + +- `except` is an array with all URIs paths taht you want to exclude from tracking. +- `exceptHeaders` is an array with all Headers that you want to exclude from tracking. + +Then replace the `TrackPageview` middleware with this one on your `bootstrap/app.php` middleware configuration: + +```diff + ->withMiddleware(function (Middleware $middleware) { + $middleware->web(append: [ +- \Pirsch\Http\Middleware\TrackPageview::class, ++ \App\Http\Middleware\TrackPageview::class, + ]); + }) +``` diff --git a/src/Http/Middleware/TrackPageview.php b/src/Http/Middleware/TrackPageview.php index 1c8f9ac..c1563eb 100644 --- a/src/Http/Middleware/TrackPageview.php +++ b/src/Http/Middleware/TrackPageview.php @@ -9,7 +9,29 @@ class TrackPageview { - public function handle(Request $request, Closure $next): mixed + /** + * The URIs that should be excluded from tracking. + * + * @var array + */ + protected array $except = [ + 'telescope/*', + 'horizon/*', + ]; + + /** + * The Headers that should be excluded from tracking. + * + * @var array + */ + protected array $exceptHeaders = [ + 'X-Livewire', + ]; + + /** + * Handle an incoming request. + */ + public function handle(Request $request, Closure $next, string ...$excepts): mixed { $response = $next($request); @@ -17,16 +39,44 @@ public function handle(Request $request, Closure $next): mixed return $response; } - if ($request->hasHeader('X-Livewire')) { - return $response; + if (! $this->inExceptArray($request, $excepts) && + ! $this->inExceptHeadersArray($request) + ) { + Pirsch::track(); } - if (str_starts_with($request->route()->uri, 'telescope/')) { - return $response; + return $response; + } + + /** + * Determine if the request has a header that should not be tracked. + */ + protected function inExceptHeadersArray(Request $request): bool + { + foreach ($this->exceptHeaders as $except) { + if ($request->hasHeader($except)) { + return true; + } } - Pirsch::track(); + return false; + } - return $response; + /** + * Determine if the request has a URI that should not be tracked. + */ + protected function inExceptArray(Request $request, array $excepts = null): bool + { + foreach (empty($excepts) ? $this->except : $excepts as $except) { + if ($except !== '/') { + $except = trim($except, '/'); + } + + if ($request->fullUrlIs($except) || $request->is($except)) { + return true; + } + } + + return false; } } diff --git a/tests/TrackPageviewTest.php b/tests/TrackPageviewTest.php index 317ba74..51e019f 100644 --- a/tests/TrackPageviewTest.php +++ b/tests/TrackPageviewTest.php @@ -22,7 +22,7 @@ $this->get('/'); - Pirsch::shouldNotHaveBeenCalled(); + Pirsch::shouldNotHaveReceived('track'); }); it('skips Livewire', function () { @@ -33,16 +33,38 @@ $this->get('/', ['X-Livewire' => 'true']); - Pirsch::shouldNotHaveBeenCalled(); + Pirsch::shouldNotHaveReceived('track'); }); it('skips Telescope', function () { Pirsch::spy(); Route::middleware(TrackPageview::class) - ->get('telescope/test', fn () => 'Hello World'); + ->get('/telescope/test', fn () => 'Hello World'); $this->get('/telescope/test'); - Pirsch::shouldNotHaveBeenCalled(); + Pirsch::shouldNotHaveReceived('track'); +}); + +it('skips Horizon', function () { + Pirsch::spy(); + + Route::middleware(TrackPageview::class) + ->get('horizon/test', fn () => 'Hello World'); + + $this->get('/horizon/test'); + + Pirsch::shouldNotHaveReceived('track'); +}); + +it('skips parameter except', function () { + Pirsch::spy(); + + Route::middleware(TrackPageview::class.':myurl/*') + ->get('myurl/test', fn () => 'Hello World'); + + $this->get('/myurl/test'); + + Pirsch::shouldNotHaveReceived('track'); });