PHPackages                             pascalkleindienst/laravel-glimpse - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. pascalkleindienst/laravel-glimpse

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

pascalkleindienst/laravel-glimpse
=================================

v0.5.1(1mo ago)2101[1 issues](https://github.com/PascalKleindienst/laravel-glimpse/issues)MITPHPPHP ^8.4CI passing

Since Mar 22Pushed 1mo agoCompare

[ Source](https://github.com/PascalKleindienst/laravel-glimpse)[ Packagist](https://packagist.org/packages/pascalkleindienst/laravel-glimpse)[ RSS](/packages/pascalkleindienst-laravel-glimpse/feed)WikiDiscussions main Synced 3w ago

READMEChangelog (8)Dependencies (25)Versions (13)Used By (0)

⚡ Glimpse Analytics
===================

[](#-glimpse-analytics)

[![Latest Version on Packagist](https://camo.githubusercontent.com/dd80c359089b44fc2879597592f0541a8263620d6873363a72b9775b3f1dff40/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f70617363616c6b6c65696e6469656e73742f6c61726176656c2d676c696d7073652e7376673f636f6c6f723d72676228353625323031383925323032343829266c6162656c3d72656c65617365267374796c653d666f722d7468652d6261646765)](https://packagist.org/packages/pascalkleindienst/laravel-glimpse)[![GitHub Tests Action Status](https://camo.githubusercontent.com/6ebd7748c285606d7a3887a78312e0277c7d9ce121c146a89180a8c5903e8893/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f70617363616c6b6c65696e6469656e73742f6c61726176656c2d676c696d7073652f74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666f722d7468652d626164676526636f6c6f723d7267622831333425323032333925323031323829)](https://github.com/PascalKleindienst/laravel-glimpse/actions/workflows/tests.yml?query=branch%3Amain)[![GitHub Code Style Action Status](https://camo.githubusercontent.com/f04964f923bb0203fb4bca2bbed5d44ac2cd6fa1ca38aa4a8668ae85da449321/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f70617363616c6b6c65696e6469656e73742f6c61726176656c2d676c696d7073652f6c696e742e796d6c3f6272616e63683d6d61696e266c6162656c3d636f64652532307374796c65267374796c653d666f722d7468652d626164676526636f6c6f723d7267622831333425323032333925323031323829)](https://github.com/PascalKleindienst/laravel-glimpse/actions/workflows/lint.yml?query=branch%3Amain)[![codecov](https://camo.githubusercontent.com/bbdea90cf719cd36006dd97541dfdb2bcddca022df35fe8d628b9ab989d2d482/68747470733a2f2f696d672e736869656c64732e696f2f636f6465636f762f632f67682f50617363616c4b6c65696e6469656e73742f6c61726176656c2d676c696d7073653f746f6b656e3d4d656c48433461747a76267374796c653d666f722d7468652d6261646765266c6f676f3d636f6465636f76)](https://codecov.io/gh/PascalKleindienst/laravel-glimpse)[![Total Downloads](https://camo.githubusercontent.com/dcc8908f91e3e8074a204b7622b9f6c3a07b4f5435ff0160b59acb64df64d2d2/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f50617363616c4b6c65696e6469656e73742f6c61726176656c2d676c696d7073653f7374796c653d666f722d7468652d626164676526636f6c6f723d72676228323439253230313135253230323229)](https://packagist.org/packages/PascalKleindienst/laravel-glimpse)[![Laravel Version](https://camo.githubusercontent.com/cb150ae233281b4c32b26d915e5a3d21cf51b04d64709a5d528d6c81df70b1d9/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c61726176656c2d253545313225374325354531332d7267622832333525323036382532303530293f7374796c653d666f722d7468652d6261646765266c6f676f3d6c61726176656c)](https://camo.githubusercontent.com/cb150ae233281b4c32b26d915e5a3d21cf51b04d64709a5d528d6c81df70b1d9/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c61726176656c2d253545313225374325354531332d7267622832333525323036382532303530293f7374796c653d666f722d7468652d6261646765266c6f676f3d6c61726176656c)[![Packagist Dependency Version](https://camo.githubusercontent.com/5c3ed6bf2d2db91c88d7f950faba4436d7724d90b7b17ae87379cfa7e6a266a4/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f646570656e64656e63792d762f50617363616c4b6c65696e6469656e73742f6c61726176656c2d676c696d7073652f7068703f7374796c653d666f722d7468652d6261646765266c6f676f3d706870266c6f676f436f6c6f723d726762283136352532303138302532303235322926636f6c6f723d7267622831363525323031383025323032353229)](https://camo.githubusercontent.com/5c3ed6bf2d2db91c88d7f950faba4436d7724d90b7b17ae87379cfa7e6a266a4/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f646570656e64656e63792d762f50617363616c4b6c65696e6469656e73742f6c61726176656c2d676c696d7073652f7068703f7374796c653d666f722d7468652d6261646765266c6f676f3d706870266c6f676f436f6c6f723d726762283136352532303138302532303235322926636f6c6f723d7267622831363525323031383025323032353229)

**Privacy-first, server-side analytics for Laravel 12+.**
No cookies. No JavaScript tracking pixel. No GDPR consent banners.
Just clean, fast, anonymous analytics built entirely on the server.

  ![Logo for pokio](.github/assets/screen-light.webp)---

Features
--------

[](#features)

- **Zero client-side footprint** — tracking is 100% server-side via a Laravel middleware
- **Session-based unique visitors** — derived from Laravel's existing session ID (SHA-256 hashed, never stored raw)
- **No PII stored** — IPs are one-way hashed with your app key; no names, emails, or identifiers
- **Cookie-free** — no new cookies introduced; uses the session cookie your app already sets
- **Livewire dashboard** — a Pulse-style real-time dashboard at `/glimpse`
- **Custom events** — `Glimpse::event('checkout', ['plan' => 'pro'])`
- **GeoIP** — country, region, city, language (MaxMind or SxGeo, optional)
- **Device detection** — browser, OS, platform (desktop/mobile/tablet)
- **Referrer classification** — organic, social, paid, email, referral, direct
- **Pre-aggregated** — dashboard queries never touch raw tables; fast at any scale
- **Queue-driven** — zero latency added to your requests

---

Requirements
------------

[](#requirements)

DependencyVersionPHP^8.4|^8.5Laravel^12.0|^13.0Livewire^3.6.4|^4.0---

Installation
------------

[](#installation)

```
composer require pascalkleindienst/laravel-glimpse
php artisan glimpse:install
```

`glimpse:install` will:

1. Publish `config/glimpse.php`
2. Publish and run the database migrations
3. Inject `TrackVisitorMiddleware` middleware into `bootstrap/app.php`
4. Run a health check and print next steps

---

Quick Start
-----------

[](#quick-start)

### 1. Register the middleware

[](#1-register-the-middleware)

The install command does this automatically. If you need to do it manually, add to `bootstrap/app.php`:

```
->withMiddleware(function (Middleware $middleware) {
    $middleware->web(append: [
        \LaravelGlimpse\Http\Middleware\TrackVisitorMiddleware::class,
    ]);
})
```

### 2. Start the queue worker

[](#2-start-the-queue-worker)

Glimpse dispatches a queued job per request so tracking adds zero latency:

```
php artisan queue:work
```

### 3. Enable the scheduler

[](#3-enable-the-scheduler)

Add to your crontab (or use Laravel's built-in scheduler):

```
* * * * * php /path/to/your/app/artisan schedule:run >> /dev/null 2>&1

```

Glimpse auto-registers two scheduled commands:

- `glimpse:aggregate` — every 5 minutes (aggregates raw data)
- `glimpse:prune` — daily at 03:00 (deletes data beyond the retention window)

### 4. Open the dashboard

[](#4-open-the-dashboard)

```
https://your-app.com/glimpse

```

---

Configuration
-------------

[](#configuration)

Publish the config file:

```
php artisan vendor:publish --tag=glimpse-config
```

```
// config/glimpse.php

return [
    /*
    |--------------------------------------------------------------------------
    | Enable / Disable Glimpse
    |--------------------------------------------------------------------------
    | Quickly toggle tracking without removing the middleware. Useful for
    | disabling in local/staging environments via your .env file.
    */
    'enabled' => env('GLIMPSE_ENABLED', true),

    /*
    |--------------------------------------------------------------------------
    | The configuration for excluding certain paths and bots
    |--------------------------------------------------------------------------
    | 'bots' - Exclude bots from tracking
    | 'paths' - Exclude paths from tracking. Use regex for matching
    | 'ips' - Exclude IPs from tracking. Use regex for matching
    */
    'exclude' => [
        'bots' => true,
        'paths' => [
            '/^glimpse$/',
            '/^admin\/?.*/',
            '/^api\/?.*/',
        ],
        'ips' => [],
    ],

    /*
    |--------------------------------------------------------------------------
    | Queue Connection & Queue Name
    |--------------------------------------------------------------------------
    | Glimpse dispatches a queued job for every hit so tracking adds zero
    | latency to your requests. Set to 'sync' during development/testing.
    */
    'queue_connection' => env('GLIMPSE_QUEUE_CONNECTION', env('QUEUE_CONNECTION', 'database')),
    'queue' => env('GLIMPSE_QUEUE', 'default'),

    /*
    |--------------------------------------------------------------------------
    | Dashboard Path & Middleware
    |--------------------------------------------------------------------------
    | The URI where the Glimpse dashboard will be available. Protect it with
    | whatever middleware makes sense for your app (typically 'auth').
    */
    'path' => env('GLIMPSE_PATH', 'glimpse'),
    'middleware' => ['web', 'auth'],

    /*
    |--------------------------------------------------------------------------
    | Session Timeout (minutes)
    |--------------------------------------------------------------------------
    | How long without activity before a visitor's session is considered
    | ended and a new one will be created on their next request.
    */
    'session_timeout' => (int) env('GLIMPSE_SESSION_TIMEOUT', 30),

    /*
    |--------------------------------------------------------------------------
    | Data Retention
    |--------------------------------------------------------------------------
    | How many days to keep raw tracking rows (sessions, page views, events).
    | Aggregate rows are kept forever by default (set null for forever).
    */
    'retention' => [
        'raw' => (int) env('GLIMPSE_RETENTION_RAW', 90),
        'aggregates' => null,
    ],

    /*
    |--------------------------------------------------------------------------
    | GeoIP Driver
    |--------------------------------------------------------------------------
    | 'maxmind'  – MaxMind GeoIP2 City database (requires a licence key and
    |              the mmdbphp extension or geoip2/geoip2 package).
    | 'sxgeo'    – SypexGeo free database bundled with the package (no key).
    | 'null'     – Disables geo resolution entirely.
    */
    'geo' => [
        'driver' => env('GLIMPSE_GEO_DRIVER', 'null'),
        'maxmind_db' => env('GLIMPSE_MAXMIND_DB', storage_path('app/glimpse/GeoLite2-City.mmdb')),
        'sxgeo_db' => env('GLIMPSE_SXGEO_DB', storage_path('app/glimpse/SxGeoCity.dat')),
    ],

    /*
    |--------------------------------------------------------------------------
    | Request Resolver
    |--------------------------------------------------------------------------
    | The following array lists the "resolvers" that will be registered with
    | Glimpse, along with their configuration. Resolvers gather information
    | about the request and return an array of attributes to be stored.
    |
    */
    'resolver' => [
        LaravelGlimpse\Resolvers\DeviceResolver::class => [],
        LaravelGlimpse\Resolvers\LanguageResolver::class => [],
        LaravelGlimpse\Resolvers\GeoResolver::class => [],
        LaravelGlimpse\Resolvers\ReferrerResolver::class => [
            'search_engines' => [
                'google', 'bing', 'yahoo', 'duckduckgo', 'baidu', 'yandex',
                'ecosia', 'startpage', 'qwant', 'brave', 'kagi', 'ask',
            ],
            'social_media' => [
                'facebook', 'twitter', 'x.com', 't.co', 'instagram', 'linkedin',
                'pinterest', 'tiktok', 'reddit', 'youtube', 'snapchat', 'whatsapp',
                'telegram', 'mastodon', 'threads', 'bluesky', 'bsky', 'discord', 'slack',
                'twitch',
            ],
            'email_clients' => [
                'mail.google', 'outlook', 'mail.yahoo', 'protonmail', 'webmail',
                'roundcube', 'mail.ru',
            ],
            // Query params that reliably indicate paid / campaign traffic.
            'paid_params' => ['gclid', 'fbclid', 'msclkid', 'ttclid', 'li_fat_id'],
        ],
    ],
];
```

---

Custom Events
-------------

[](#custom-events)

Track any meaningful action in your app:

```
use LaravelGlimpse\Facades\Glimpse;

// Simple event
Glimpse::event('signup');

// Event with payload
Glimpse::event('checkout', [
    'plan'  => 'pro',
    'value' => 99,
]);

// Virtual page view (for SPAs / AJAX navigation)
Glimpse::page('/checkout/step-2', 'Checkout — Step 2');

// Swallow invalid names silently instead of throwing
Glimpse::dispatchSilently($untrustedName, $properties);
```

### Using the global helper

[](#using-the-global-helper)

```
glimpse('signup');
glimpse('checkout', ['plan' => 'pro']);
glimpse(); // returns the Glimpse instance
```

### Associating events from queued jobs

[](#associating-events-from-queued-jobs)

```
// In your controller — capture the hash before dispatching
$hash = Glimpse::currentSessionHash();
dispatch(new ProcessOrderJob($orderId, $hash));

// Inside the job
Glimpse::event('order_processed', ['id' => $orderId], $hash);
```

### Listening to dispatched events

[](#listening-to-dispatched-events)

```
use LaravelGlimpse\Events\GlimpseEventDispatchedEvent;

Event::listen(GlimpseEventDispatchedEvent::class, function ($e) {
    if ($e->name === 'enterprise_signup') {
        Notification::route('slack', config('services.slack.sales'))
            ->notify(new NewEnterpriseSignupNotification($e->properties));
    }
});
```

---

Dashboard Access Control
------------------------

[](#dashboard-access-control)

By default, any authenticated user can access the dashboard. Customise this in a service provider:

```
use LaravelGlimpse\GlimpseGate;
use Illuminate\Http\Request;

// In AppServiceProvider::boot()
GlimpseGate::using(function (Request $request): bool {
    return $request->user()?->hasRole('admin') ?? false;
});
```

---

Querying Analytics in Code
--------------------------

[](#querying-analytics-in-code)

Access the full query API anywhere in your application:

```
use LaravelGlimpse\Facades\Glimpse;
use LaravelGlimpse\Values\DateRange;
use Illuminate\Support\Carbon;

// Quick summary
$stats = Glimpse::query()->summary(DateRange::last7Days());
$stats = Glimpse::query()->summary(DateRange::today());
$stats = Glimpse::query()->summary(DateRange::custom(Carbon::parse('2026-01-01'), Carbon::now());

// $stats = [
//   'visitors'     => 1240,
//   'page_views'   => 4823,
//   'sessions'     => 1240,
//   'bounce_rate'  => 42.3,
//   'avg_duration' => 127.0,
// ]

// Full query API
$query = Glimpse::query();

$pages     = $query->topPages(DateRange::last30Days());
$channels  = $query->topChannels(DateRange::last30Days());
$countries = $query->topCountries(DateRange::last30Days());
$browsers  = $query->topBrowsers(DateRange::last7Days());
$events    = $query->topEvents(DateRange::last7Days());
$series    = $query->timeSeries(DateRange::last7Days());
```

---

---

GeoIP Setup
-----------

[](#geoip-setup)

Geo resolution is **disabled** by default (driver = `null`). To enable:

### MaxMind GeoLite2 (recommended)

[](#maxmind-geolite2-recommended)

1. Sign up for a free MaxMind account and download `GeoLite2-City.mmdb`
2. Place the file at `storage/app/glimpse/GeoLite2-City.mmdb`
3. Set in `.env`:

```
GLIMPSE_GEO_DRIVER=maxmind
GLIMPSE_MAXMIND_DB=/absolute/path/to/GeoLite2-City.mmdb
```

### SypexGeo (no sign-up required)

[](#sypexgeo-no-sign-up-required)

1. Download `SxGeoCity.dat` and `SxGeo.php` from [sypexgeo.net](https://sypexgeo.net)
2. Place both files at `storage/app/glimpse/`
3. Set in `.env`:

```
GLIMPSE_GEO_DRIVER=sxgeo
```

---

Artisan Commands
----------------

[](#artisan-commands)

CommandDescription`glimpse:install`Install Glimpse (publish, migrate, wire middleware)`glimpse:aggregate`Roll raw data into aggregate buckets (auto-scheduled)`glimpse:prune`Delete data beyond retention window (auto-scheduled)`glimpse:backfill`Re-aggregate a historical date range### Backfill historical data

[](#backfill-historical-data)

```
# Backfill the last 90 days
php artisan glimpse:backfill --days=90

# Backfill a specific range
php artisan glimpse:backfill --from=2024-01-01 --to=2024-03-31

# Process in smaller chunks to limit memory usage
php artisan glimpse:backfill --days=365 --chunk=7
```

---

Customising the Dashboard
-------------------------

[](#customising-the-dashboard)

Publish the views to override them:

```
php artisan vendor:publish --tag=glimpse-views
```

Views are published to `resources/views/vendor/glimpse/`.

---

How It Works
------------

[](#how-it-works)

### Session identity

[](#session-identity)

On every request the `TrackVisitorMiddleware` computes:

```
session_hash = SHA-256(laravel_session_id)

```

This is stored as the visitor identity. The raw session ID is never persisted. When the session expires (default 2 hours in Laravel), so does the identity — genuinely ephemeral.

### Request lifecycle

[](#request-lifecycle)

```
HTTP Request
    │
    ├─ TrackVisitorMiddleware (sync — reads cache only)
    │      └─ Dispatch ProcessVisitJob to queue
    │
    └─ Response returned immediately ← zero DB writes in the request

Queue worker (async)
    └─ ProcessVisitJob
           ├─ GeoResolver    (IP → country/city)
           ├─ DeviceResolver (UA → browser/OS/platform)
           ├─ LanguageResolver (Accept-Language Header → language)
           ├─ ReferrerResolver (referer → channel)
           └─ Write to glimpse_sessions + glimpse_page_views

```

### Aggregation

[](#aggregation)

Every 5 minutes, `glimpse:aggregate` reads raw rows and upserts pre-computed buckets into `glimpse_aggregates`. The dashboard **only reads from `glimpse_aggregates`** — it never queries raw tables, so it's fast at any volume.

---

Privacy
-------

[](#privacy)

Glimpse is designed to be GDPR/ePrivacy compliant by default:

- **No cookies introduced** — uses the session cookie already set by Laravel
- **No PII stored** — IPs are one-way hashed (SHA-256 + app key) before storage
- **No third-party requests** — all data stays on your server
- **No cross-site tracking** — identifiers are session-scoped
- **No fingerprinting** — User-Agent is parsed but never stored

> **Legal note**: Glimpse minimizes data collection but you are responsible for your own compliance. Consult a legal professional for advice specific to your jurisdiction.

---

Testing
-------

[](#testing)

```
composer test
```

---

License
-------

[](#license)

MIT — see [LICENSE](LICENSE.md).

###  Health Score

40

—

FairBetter than 86% of packages

Maintenance79

Regular maintenance activity

Popularity16

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 94.7% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~6 days

Total

8

Last Release

57d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/367c097ec42aec6ed007853fbec64d138734606e71574341f970e273b3efe7fd?d=identicon)[PascalKleindienst](/maintainers/PascalKleindienst)

---

Top Contributors

[![PascalKleindienst](https://avatars.githubusercontent.com/u/3470866?v=4)](https://github.com/PascalKleindienst "PascalKleindienst (71 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (4 commits)")

---

Tags

analyticscookieless-trackinglaravellivewiretracking

###  Code Quality

TestsPest

Static AnalysisPHPStan, Rector

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/pascalkleindienst-laravel-glimpse/health.svg)

```
[![Health](https://phpackages.com/badges/pascalkleindienst-laravel-glimpse/health.svg)](https://phpackages.com/packages/pascalkleindienst-laravel-glimpse)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3345.1M337](/packages/psalm-plugin-laravel)[laravel/pulse

Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.

1.7k14.1M122](/packages/laravel-pulse)[laravel/cashier

Laravel Cashier provides an expressive, fluent interface to Stripe's subscription billing services.

2.5k28.4M137](/packages/laravel-cashier)[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9742.3M121](/packages/roots-acorn)[flarum/core

Delightfully simple forum software.

201.4M2.2k](/packages/flarum-core)[pressbooks/pressbooks

Pressbooks is an open source book publishing tool built on a WordPress multisite platform. Pressbooks outputs books in multiple formats, including PDF, EPUB, web, and a variety of XML flavours, using a theming/templating system, driven by CSS.

45344.0k1](/packages/pressbooks-pressbooks)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
