A powerful Laravel 9+ package for tracking user device activities, managing multi-device sessions, and monitoring user login statistics.
- Features
- Requirements
- Installation
- Configuration
- Usage
- Statistics
- Dashboard
- API Endpoints
- Artisan Commands
- Troubleshooting
-
Multi-Device Session Management
- Track devices separately for web and API guards
- View all devices a user is logged in from
- Logout specific device, current device, or all devices at once
-
Comprehensive Activity Logging
- Login/logout events
- Device information (OS, browser, device type)
- IP address and geolocation
- Session duration and activity timestamps
-
Statistics Dashboard (20+ Stats)
- Active sessions count
- Logins by country, OS, browser, device type
- Top active users
- Login success rate
- Session duration statistics
- Hourly/daily activity trends
-
Configurable Data Retention
- Set how long to keep data (days/years)
- Auto-cleanup old records
- Manual cleanup command
-
SQLite Support
- Lightweight database for activity storage
- Easy to setup and maintain
- PHP 8.0+
- Laravel 9.0, 10.0, or 11.0
- SQLite PHP extension (for SQLite storage)
jenssegers/agentpackage (for device detection)
composer require baligs/user-device-activityphp artisan device-activity:installThis command will:
- Create SQLite database file
- Publish configuration
- Publish migrations
- Run migrations
Add to your .env file:
# Database
DEVICE_ACTIVITY_DB_CONNECTION=sqlite
DEVICE_ACTIVITY_DB_PATH=database/user_device_activity.sqlite
# Retention (keep data for 365 days)
DEVICE_ACTIVITY_RETENTION_DAYS=365
# Session limits
DEVICE_ACTIVITY_MULTIPLE_SESSIONS=true
DEVICE_ACTIVITY_MAX_SESSIONS=5
# IP Lookup (for country detection)
DEVICE_ACTIVITY_IP_LOOKUP=trueIf you prefer manual setup:
# 1. Publish configuration
php artisan vendor:publish --provider="Baligs\UserDeviceActivity\Providers\UserDeviceActivityServiceProvider" --tag="user-device-activity-config"
# 2. Publish migrations
php artisan vendor:publish --provider="Baligs\UserDeviceActivity\Providers\UserDeviceActivityServiceProvider" --tag="user-device-activity-migrations"
# 3. Publish views (optional - for custom dashboard)
php artisan vendor:publish --provider="Baligs\UserDeviceActivity\Providers\UserDeviceActivityServiceProvider" --tag="user-device-activity-views"
# 4. Create SQLite database
touch database/user_device_activity.sqlite
# 5. Run migrations
php artisan migrateEdit config/user-device-activity.php:
'database' => [
'connection' => env('DEVICE_ACTIVITY_DB_CONNECTION', 'sqlite'),
'database_path' => env('DEVICE_ACTIVITY_DB_PATH', database_path('user_device_activity.sqlite')),
],'retention' => [
'enabled' => env('DEVICE_ACTIVITY_RETENTION_ENABLED', true),
'days' => env('DEVICE_ACTIVITY_RETENTION_DAYS', 365),
'cleanup_batch_size' => 1000,
],'guards' => [
'web' => [
'enabled' => true,
'session_lifetime' => 120,
'track_ip' => true,
'track_user_agent' => true,
'track_device_type' => true,
'track_os' => true,
'track_browser' => true,
'track_country' => true,
],
'api' => [
'enabled' => true,
'token_lifetime' => 20160,
'track_ip' => true,
'track_user_agent' => true,
'track_device_type' => true,
'track_os' => true,
'track_browser' => true,
'track_country' => true,
],
],'features' => [
'allow_multiple_sessions' => env('DEVICE_ACTIVITY_MULTIPLE_SESSIONS', true),
'max_sessions_per_user' => env('DEVICE_ACTIVITY_MAX_SESSIONS', 5),
'notify_on_new_login' => env('DEVICE_ACTIVITY_NOTIFY_NEW_LOGIN', false),
'auto_cleanup' => env('DEVICE_ACTIVITY_AUTO_CLEANUP', true),
],'ip_lookup' => [
'enabled' => env('DEVICE_ACTIVITY_IP_LOOKUP', true),
'service' => env('DEVICE_ACTIVITY_IP_SERVICE', 'ip-api.com'),
],The DeviceActivityHelper provides a simple interface for all device activity operations.
use Baligs\UserDeviceActivity\Helpers\DeviceActivityHelper;
// In your LoginController
public function login(Request $request)
{
if (Auth::attempt($credentials)) {
$request->session()->regenerate();
// Track the login session
$session = DeviceActivityHelper::createSession(Auth::user(), 'web');
return redirect()->intended('/dashboard');
}
}// Get all sessions for a user
$sessions = DeviceActivityHelper::getUserSessions($user->id, 'web');
// Get only active sessions
$activeSessions = DeviceActivityHelper::getActiveUserDevices($user->id, 'web');
// Get current session
$currentSession = DeviceActivityHelper::getCurrentSession('web');
// Get session by ID
$session = DeviceActivityHelper::getSessionById($sessionId);// Logout specific device
DeviceActivityHelper::logoutSession($sessionId);
// Logout current session
DeviceActivityHelper::logoutCurrentSession('web');
// Logout all sessions (for a specific guard)
$count = DeviceActivityHelper::logoutAllSessions($user->id, 'web');
// Logout all devices (across all guards)
$count = DeviceActivityHelper::logoutAllDevices($user->id);// Check if user is online (active in last 5 minutes)
$isOnline = DeviceActivityHelper::isUserOnline($user->id);
// Check if session is active
$isActive = DeviceActivityHelper::isSessionActive($sessionId);
// Get last login info
$lastLogin = DeviceActivityHelper::getLastLogin($user->id, 'web');
$lastLoginTime = DeviceActivityHelper::getLastLoginTime($user->id, 'web');DeviceActivityHelper::logActivity('profile_update', $user->id, 'web', [
'field' => 'email',
'old_value' => 'old@example.com',
'new_value' => 'new@example.com',
]);Add the HasDeviceActivity trait to your User model for convenient methods:
// app/Models/User.php
use Baligs\UserDeviceActivity\Traits\HasDeviceActivity;
class User extends Authenticatable
{
use HasDeviceActivity;
}Now you can use:
// Get user's active sessions
$user->getActiveSessions('web');
// Get all sessions
$user->getAllSessions('web');
// Get last login
$user->getLastLogin('web');
// Check if online
$user->isOnline();
// Get activity stats
$stats = $user->getActivityStats('web', 30);
// Get recent activities
$activities = $user->getRecentActivities(50, 'web');
// Logout methods
$user->logoutAllSessions('web');
$user->logoutAllDevices();Here's a complete example of integrating the package with your login controller:
// app/Http/Controllers/Auth/LoginController.php
use Baligs\UserDeviceActivity\Helpers\DeviceActivityHelper;
class LoginController extends Controller
{
public function login(Request $request)
{
$this->validateLogin($request);
if (Auth::attempt($this->credentials($request))) {
$request->session()->regenerate();
// Track device activity on login
DeviceActivityHelper::createSession(Auth::user(), 'web');
return $this->sendLoginResponse($request);
}
// Track failed login attempt
DeviceActivityHelper::logActivity('login_failed', 0, 'web', [
'email' => $request->email,
'ip' => $request->ip(),
]);
return $this->sendFailedLoginResponse($request);
}
public function logout(Request $request)
{
// Track logout before logging out
DeviceActivityHelper::logoutCurrentSession('web');
Auth::logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect('/');
}
}For API authentication (Sanctum):
// app/Http/Controllers/Auth/ApiAuthController.php
use Baligs\UserDeviceActivity\Helpers\DeviceActivityHelper;
use Laravel\Sanctum\Sanctum;
public function login(Request $request)
{
$request->validate([
'email' => 'required|email',
'password' => 'required',
]);
$user = User::where('email', $request->email)->first();
if (!$user || !Hash::check($request->password, $user->password)) {
DeviceActivityHelper::logActivity('login_failed', 0, 'api', [
'email' => $request->email,
]);
return response()->json(['error' => 'Invalid credentials'], 401);
}
// Create Sanctum token
$token = $user->createToken('api-token')->plainTextToken;
// Track the session
DeviceActivityHelper::createSession($user, 'api', $token);
return response()->json([
'user' => $user,
'token' => $token,
]);
}
public function logout(Request $request)
{
// Revoke current token
$request->user()->currentAccessToken()->delete();
// Track logout
DeviceActivityHelper::logoutCurrentSession('api');
return response()->json(['message' => 'Logged out']);
}The package provides middleware to automatically track page views:
// routes/web.php
Route::middleware(['auth', 'track.device.activity:web'])->group(function () {
// All routes here will have activity tracked
Route::get('/dashboard', [DashboardController::class, 'index']);
});
// routes/api.php
Route::middleware(['auth:sanctum', 'track.device.activity:api'])->group(function () {
// API routes with activity tracking
Route::get('/user/profile', [ProfileController::class, 'show']);
});$stats = DeviceActivityHelper::getOverviewStats(30);
// Returns: total_active_sessions, total_logins, unique_users, etc.$allStats = DeviceActivityHelper::getAllStats(30);
// Returns comprehensive stats including all categories// By Country
$byCountry = DeviceActivityHelper::getLoginsByCountry(30);
// By Device Type
$byDeviceType = DeviceActivityHelper::getActiveUsersByDeviceType(30);
// By Operating System
$byOS = DeviceActivityHelper::getActiveUsersByOS(30);
// By Browser
$byBrowser = DeviceActivityHelper::getActiveUsersByBrowser(30);
// Top Active Users
$topUsers = DeviceActivityHelper::getTopActiveUsers(30, 10);
// Login Success Rate
$successRate = DeviceActivityHelper::getLoginSuccessRate(30);
// Returns: total_attempts, successful, failed, success_rate
// Session Stats
$sessionStats = DeviceActivityHelper::getSessionStats(30);
// Returns: total_sessions, active_sessions, completed_sessions, avg_duration_minutes
// Guard Stats
$guardStats = DeviceActivityHelper::getGuardStats(30);
// Logins by Day
$loginsByDay = DeviceActivityHelper::getLoginsByDay(30);
// Hourly Activity
$hourlyActivity = DeviceActivityHelper::getHourlyActivity(7);
// Recent Logins
$recentLogins = DeviceActivityHelper::getRecentLogins(20);
// Activity Breakdown
$breakdown = DeviceActivityHelper::getActivityBreakdown(30);Access the dashboard at: /admin/device-activity
| Route | Description |
|---|---|
/admin/device-activity |
Main dashboard with all stats |
/admin/device-activity/sessions |
View all sessions |
/admin/device-activity/activities |
View all activities |
/admin/device-activity/user/{id}/devices |
View user's devices |
- Active Sessions - Total active sessions
- Total Logins - Successful logins count
- Unique Users - Distinct users
- Countries - Unique countries count
- Online Now - Currently online users
- Total Logouts - Logout events count
- Failed Logins - Failed login attempts
- Devices Logged Out - Manual device logouts
- By Device Type - Desktop/Mobile/Tablet
- By Operating System - Windows/Mac/Linux/Android/iOS
- By Browser - Chrome/Firefox/Safari/Edge
- Login Success Rate - Success percentage
- Guard Statistics - Web vs API usage
- Session Statistics - Session counts & duration
- Activity Breakdown - All activity types
- Top Countries - Most active countries
- Top Active Users - Most active users
- Recent Logins - Latest login activities
- Hourly Activity - Activity by hour
- Logins by Day - Daily login trends
GET /api/device-activity/sessions
- List all sessions for current user
GET /api/device-activity/sessions/active
- List active sessions only
GET /api/device-activity/sessions/current
- Get current session
GET /api/device-activity/sessions/{id}
- Get specific session
DELETE /api/device-activity/sessions/{id}
- Logout specific session
POST /api/device-activity/sessions/{id}/logout
- Logout specific session
POST /api/device-activity/sessions/logout-current
- Logout current session
POST /api/device-activity/sessions/logout-all
- Logout all sessions for current user
POST /api/device-activity/sessions/logout-all-devices
- Logout all devices (all guards)
GET /api/device-activity/sessions/stats
- Get user's activity stats
GET /api/device-activity/stats/overview
- Overview statistics
GET /api/device-activity/stats/by-country
- Logins by country
GET /api/device-activity/stats/by-device-type
- By device type
GET /api/device-activity/stats/by-os
- By operating system
GET /api/device-activity/stats/by-browser
- By browser
GET /api/device-activity/stats/top-users
- Top active users
GET /api/device-activity/stats/logins-by-day
- Daily login trends
GET /api/device-activity/stats/activity-breakdown
- All activity types
GET /api/device-activity/stats/hourly-activity
- Hourly activity
GET /api/device-activity/stats/session-stats
- Session statistics
GET /api/device-activity/stats/guard-stats
- Guard statistics
GET /api/device-activity/stats/login-success-rate
- Login success rate
GET /api/device-activity/stats/all
- All statistics combined
{
"success": true,
"data": {
"total_active_sessions": 15,
"total_logins": 245,
"total_logouts": 230,
"unique_users": 42,
"unique_countries": 8,
"failed_logins": 12,
"online_users": 5,
"devices_logged_out": 8
}
}php artisan device-activity:install# Cleanup using default retention days
php artisan device-activity:cleanup
# Cleanup data older than 30 days
php artisan device-activity:cleanup --days=30Enable automatic cleanup in config:
// config/user-device-activity.php
'features' => [
'auto_cleanup' => true, // Runs daily at midnight
],Or add to your app/Console/Kernel.php:
protected function schedule(Schedule $schedule): void
{
$schedule->command('device-activity:cleanup')->daily();
}Error: "could not find driver"
- Make sure SQLite PHP extension is enabled
- Or configure MySQL/PostgreSQL in config
Error: "Database does not exist"
- Create the SQLite file:
touch database/user_device_activity.sqlite - Or ensure MySQL database exists
Country shows as "Unknown"
- Check if
DEVICE_ACTIVITY_IP_LOOKUP=truein .env - Verify internet connection (IP lookup requires external API)
- Localhost (127.0.0.1) won't show country info
Login not creating session
- Ensure
DeviceActivityHelper::createSession()is called after successful login - Check if user object has
idproperty
Middleware not tracking
- Add
track.device.activity:webortrack.device.activity:apimiddleware - Ensure middleware runs after authentication
Helper methods not found
- Clear cache:
php artisan config:clear - Check if package is registered in
config/app.php
Cannot create database file
chmod 775 database
touch database/user_device_activity.sqlite
chmod 664 database/user_device_activity.sqliteFor issues or feature requests, visit:
- GitHub: https://github.com/baligs/user-device-activity
- Packagist: https://packagist.org/packages/baligs/user-device-activity
MIT License - Copyright (c) 2024 baligs