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

Filament User Activity Laravel Package

edwink/filament-user-activity

A Filament plugin that brings user activity tracking to your admin panel, letting you log, view, and filter user actions and events so you can audit changes and monitor who did what, when, and from where.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package and publish its assets:

composer require edwink/filament-user-activity
php artisan vendor:publish --tag="filament-user-activity-config"
php artisan vendor:publish --tag="filament-user-activity-migrations"
php artisan migrate

Register the plugin on the panel(s) where you want activity tracked and surfaced:

public function panel(Panel $panel): Panel
{
    return $panel
        ->plugin(FilamentUserActivityPlugin::make());
}

Where to look first: the published config/filament-user-activity.php. That file is the contract for everything else — the inactivity window (how many minutes ago a hit still counts as "online"), the table/connection used for storage, the auth guard being tracked, and any polling interval used by the widget. Read it before touching the widget or the middleware.

First use case: drop the active-users widget onto the dashboard so admins can see who is currently in the app. Register it in your panel's ->widgets([...]) array (or discover it via php artisan filament:widget), and you have a live "who's online" table in minutes. The natural second step is activity history — filtering the same data by user and time range to answer "what has this account been doing?"

Implementation Patterns

Middleware-driven capture. The package records a visit per authenticated request, typically by stamping last_activity_at (and IP/user agent) on a row keyed by user. That means you don't call anything manually — the panel's web middleware group does the work. If you need tracking on non-Filament routes (an API, a public area), register the tracking middleware there too, and confirm it runs after auth so Auth::id() is populated.

Panel vs. global scope. In multi-panel apps (admin + app + vendor), decide whether activity is one shared pool or per-panel. Most teams want a single pool for "who's online" but a panel column/filter for "who's in the admin panel." If the package doesn't expose a panel column out of the box, add one via a small migration or a computed attribute rather than forking.

Tenant scoping. In a tenancy setup, "active users" is almost always "active users in this tenant." Wrap the widget's query in the tenant scope (->where('tenant_id', Filament::getTenant()->id)) and make sure the tracking middleware writes the tenant too — otherwise your widget leaks names across tenants, which is both a UX and a privacy problem.

Retention & pruning. Activity rows grow linearly with traffic. Add the package's model to your pruneable schedule ($schedule->command('model:prune')) or a bespoke activity:prune --days=30 command. Do this on day one, not after the table hits 50M rows.

Dashboard composition. Combine the active-users widget with Filament's chart widgets to show logins per day, per role, per panel. Same underlying table, different aggregation — cheapest way to make the data feel useful.

Gotchas and Tips

  • Guard mismatch. If you use a non-default guard (admin, staff), the plugin will silently show nothing until the config's guard is set to match the panel's authGuard(). This is the #1 "it's installed but empty" cause.
  • Middleware ordering. Tracking must run after the session/auth middleware. If you register it manually in bootstrap/app.php, put it in the web group, not the global stack.
  • Timezone drift. "Online in the last 5 minutes" is evaluated against DB time. If the app timezone and the database timezone diverge, the widget quietly lies. Store UTC and convert at display, or set both to the same zone.
  • Polling load. Live "online now" widgets poll. On a busy dashboard this becomes a real query-per-user-per-interval. Keep polling at 30–60s, ensure an index on (user_id, last_activity_at), and consider caching the count for the header badge separately from the table.
  • Missing index. The table is small on day one and painful at 100k rows. Add the composite index in the same migration you publish — don't wait for the slow query to find you.
  • Migration collisions. If you already track activity (e.g. spatie/laravel-activitylog), don't duplicate storage. Point the config at the existing table if supported, or write a small adapter — two sources of truth for "last seen" will disagree within a week.
  • Testing. Freeze time with Carbon::setTestNow() and assert on the inactivity boundary — off-by-one on the window is the most common subtle bug (is it >= or > five minutes?).
  • Extension points. The widget and model are the intended override seams: sub-class the widget to change columns/query, and publish the views if you need the markup to match your theme. Prefer that over editing vendor files, so minor releases (this package ships frequently) don't break you.
  • Version pinning. Check the Filament major version required by the release before upgrading — a Filament v3→v4 bump usually needs a matching plugin bump.
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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
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