{"id":49772842,"url":"https://github.com/ghdj/laravel-visitor-tracker","last_synced_at":"2026-05-11T14:00:04.086Z","repository":{"id":354406976,"uuid":"1141568046","full_name":"GhDj/laravel-visitor-tracker","owner":"GhDj","description":"A Laravel package for visitor tracking with analytics, geolocation, and bot detection - zero external dependencies ","archived":false,"fork":false,"pushed_at":"2026-04-28T12:02:29.000Z","size":81,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-11T13:59:28.443Z","etag":null,"topics":["analytics","bot-detection","gdpr","laravel","privacy","statistics","visitor-tracking","zero-dependency"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/GhDj.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-25T02:44:45.000Z","updated_at":"2026-04-28T11:53:49.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/GhDj/laravel-visitor-tracker","commit_stats":null,"previous_names":["ghdj/laravel-visitor-tracker"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/GhDj/laravel-visitor-tracker","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GhDj%2Flaravel-visitor-tracker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GhDj%2Flaravel-visitor-tracker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GhDj%2Flaravel-visitor-tracker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GhDj%2Flaravel-visitor-tracker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GhDj","download_url":"https://codeload.github.com/GhDj/laravel-visitor-tracker/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GhDj%2Flaravel-visitor-tracker/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32897941,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-10T13:40:02.631Z","status":"online","status_checked_at":"2026-05-11T02:00:05.975Z","response_time":120,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["analytics","bot-detection","gdpr","laravel","privacy","statistics","visitor-tracking","zero-dependency"],"created_at":"2026-05-11T14:00:03.203Z","updated_at":"2026-05-11T14:00:04.079Z","avatar_url":"https://github.com/GhDj.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Laravel Visitor Tracker\n\n[![Tests](https://github.com/ghdj/laravel-visitor-tracker/actions/workflows/tests.yml/badge.svg)](https://github.com/ghdj/laravel-visitor-tracker/actions/workflows/tests.yml)\n[![Latest Version on Packagist](https://img.shields.io/packagist/v/ghdj/laravel-visitor-tracker.svg)](https://packagist.org/packages/ghdj/laravel-visitor-tracker)\n[![License](https://img.shields.io/packagist/l/ghdj/laravel-visitor-tracker.svg)](https://packagist.org/packages/ghdj/laravel-visitor-tracker)\n\nA comprehensive visitor tracking package for Laravel applications with analytics, geolocation, and bot detection.\n\n**🚀 Zero External Dependencies** - Uses only Laravel's built-in features and native PHP for all functionality.\n\n## Features\n\n- 📊 **Comprehensive Tracking** - Track page views, unique visitors, and sessions\n- 🤖 **Native Bot Detection** - Detect 100+ bots/crawlers without external packages\n- 📱 **Native Device Detection** - Identify browsers, platforms, and device types using regex\n- 🌍 **Geolocation** - Optional IP-based location tracking (using Laravel's HTTP client)\n- 🔒 **GDPR Compliant** - GDPR Safe Mode for consent-free tracking, IP anonymization, DNT support\n- ⚡ **Performance** - Queue support for async tracking, statistics caching\n- 📈 **Rich Statistics** - Browser, platform, device, country, referrer analytics\n- 🎯 **Flexible Exclusions** - Exclude paths, IPs, user agents, status codes\n- 🔧 **Zero Dependencies** - Only uses Laravel's illuminate packages\n\n## Requirements\n\n- PHP 8.1+\n- Laravel 10.x, 11.x, or 12.x\n\n## Installation\n\n```bash\ncomposer require ghdj/laravel-visitor-tracker\n```\n\nPublish the configuration file:\n\n```bash\nphp artisan vendor:publish --tag=\"visitor-tracker-config\"\n```\n\nRun the migrations:\n\n```bash\nphp artisan migrate\n```\n\n## Configuration\n\nThe configuration file is located at `config/visitor-tracker.php`. Key options include:\n\n```php\nreturn [\n    // Enable/disable tracking globally\n    'enabled' =\u003e env('VISITOR_TRACKER_ENABLED', true),\n    \n    // Paths to exclude from tracking\n    'exclude' =\u003e [\n        'paths' =\u003e ['api/*', 'admin/*'],\n        'methods' =\u003e ['OPTIONS', 'HEAD'],\n        'status_codes' =\u003e [301, 302, 404, 500],\n        'ips' =\u003e [],\n        'user_agents' =\u003e [],\n    ],\n    \n    // Bot tracking\n    'bots' =\u003e [\n        'track' =\u003e false,\n        'detect' =\u003e true,\n        'additional_patterns' =\u003e [], // Add custom bot patterns\n    ],\n    \n    // Custom parser patterns\n    'parser' =\u003e [\n        'additional_browsers' =\u003e [], // Add custom browser patterns\n        'additional_platforms' =\u003e [], // Add custom platform patterns\n    ],\n    \n    // Geolocation (optional - uses Laravel HTTP client)\n    'geolocation' =\u003e [\n        'enabled' =\u003e env('VISITOR_TRACKER_GEOLOCATION', false),\n        'provider' =\u003e 'ip-api', // ip-api (free), ipinfo, ipapi\n    ],\n    \n    // GDPR compliance\n    'privacy' =\u003e [\n        'gdpr_safe_mode' =\u003e env('VISITOR_TRACKER_GDPR_SAFE', false),\n        'anonymize_ip' =\u003e env('VISITOR_TRACKER_ANONYMIZE_IP', false),\n        'respect_dnt' =\u003e true,\n    ],\n    \n    // Data retention\n    'retention' =\u003e [\n        'days' =\u003e 90,\n    ],\n    \n    // Queue for async tracking\n    'queue' =\u003e [\n        'enabled' =\u003e env('VISITOR_TRACKER_QUEUE', false),\n    ],\n];\n```\n\n## Usage\n\n### Middleware\n\nAdd the tracking middleware to your routes:\n\n```php\n// In routes/web.php\nRoute::middleware(['track-visitor'])-\u003egroup(function () {\n    Route::get('/', [HomeController::class, 'index']);\n    // ... more routes\n});\n\n// Or globally in bootstrap/app.php (Laravel 11)\n-\u003ewithMiddleware(function (Middleware $middleware) {\n    $middleware-\u003eweb(append: [\n        \\Ghdj\\VisitorTracker\\Middleware\\TrackVisitor::class,\n    ]);\n})\n```\n\n### Using the Facade\n\n```php\nuse Ghdj\\VisitorTracker\\Facades\\VisitorTracker;\n\n// Get statistics\n$stats = VisitorTracker::stats();\n\n// Total visitors (unique)\n$totalVisitors = $stats-\u003etotalVisitors();\n\n// Total page views\n$totalPageViews = $stats-\u003etotalPageViews();\n\n// Currently online visitors\n$onlineNow = $stats-\u003eonlineVisitors();\n\n// Today's visitors\n$todayVisitors = $stats-\u003etodayVisitors();\n\n// Visitors in last N days\n$weeklyVisitors = $stats-\u003evisitorsLastDays(7);\n\n// Most visited pages\n$topPages = $stats-\u003emostVisitedPages(10);\n\n// Top referrers\n$topReferrers = $stats-\u003etopReferrers(10);\n\n// Browser statistics\n$browsers = $stats-\u003ebrowserStats();\n\n// Platform/OS statistics\n$platforms = $stats-\u003eplatformStats();\n\n// Device type statistics\n$devices = $stats-\u003edeviceStats();\n\n// Country statistics (requires geolocation)\n$countries = $stats-\u003ecountryStats();\n\n// Summary of all stats\n$summary = $stats-\u003esummary();\n```\n\n### Using the Helper Function\n\n```php\n// Get tracker instance\n$tracker = visitor();\n\n// Get statistics\n$stats = visitor()-\u003estats()-\u003esummary();\n$online = visitor_stats()-\u003eonlineVisitors();\n```\n\n### Blade Directives\n\n```blade\n\u003cdiv class=\"stats\"\u003e\n    \u003cp\u003eTotal Visitors: @totalVisitors\u003c/p\u003e\n    \u003cp\u003eTotal Page Views: @totalPageViews\u003c/p\u003e\n    \u003cp\u003eOnline Now: @onlineVisitors\u003c/p\u003e\n    \u003cp\u003eToday's Visitors: @todayVisitors\u003c/p\u003e\n\u003c/div\u003e\n```\n\n### Working with Models\n\n```php\nuse Ghdj\\VisitorTracker\\Models\\Visitor;\nuse Ghdj\\VisitorTracker\\Models\\Visit;\n\n// Get all visitors\n$visitors = Visitor::all();\n\n// Get online visitors\n$online = Visitor::online()-\u003eget();\n\n// Get visitors excluding bots\n$humans = Visitor::excludeBots()-\u003eget();\n\n// Get authenticated visitors only\n$authenticated = Visitor::authenticated()-\u003eget();\n\n// Get visitors from date range\n$recent = Visitor::between(now()-\u003esubWeek(), now())-\u003eget();\n\n// Get visits for a specific path\n$homeVisits = Visit::path('/')-\u003eget();\n\n// Get visits with referrers\n$referred = Visit::withReferrer()-\u003eget();\n```\n\n### Using Native Services Directly\n\n```php\nuse Ghdj\\VisitorTracker\\Services\\UserAgentParser;\nuse Ghdj\\VisitorTracker\\Services\\BotDetector;\n\n// Parse user agent\n$parser = new UserAgentParser();\n$result = $parser-\u003eparse($request-\u003euserAgent());\n// Returns: ['browser' =\u003e 'Chrome', 'browser_version' =\u003e '120.0', 'platform' =\u003e 'Windows', ...]\n\n// Detect bots\n$detector = new BotDetector();\n$isBot = $detector-\u003eisBot($request-\u003euserAgent());\n$botName = $detector-\u003egetBotName($request-\u003euserAgent());\n$category = $detector-\u003egetBotCategory($request-\u003euserAgent()); // search_engine, social_media, ai_bot, etc.\n```\n\n### Adding Custom Patterns\n\n```php\n// Add custom browser detection\n$parser = new UserAgentParser();\n$parser-\u003eaddBrowserPatterns([\n    'MyCustomBrowser' =\u003e '/MyCustomBrowser\\/([0-9.]+)/',\n]);\n\n// Add custom bot detection\n$detector = new BotDetector();\n$detector-\u003eaddPatterns(['mycustombot', 'anotherbot']);\n$detector-\u003eaddBotNames(['mycustombot' =\u003e 'My Custom Bot']);\n\n// Or via config\n// config/visitor-tracker.php\n'parser' =\u003e [\n    'additional_browsers' =\u003e [\n        'MyBrowser' =\u003e '/MyBrowser\\/([0-9.]+)/',\n    ],\n],\n'bots' =\u003e [\n    'additional_patterns' =\u003e ['mycustombot'],\n],\n```\n\n### Listening to Events\n\n```php\nuse Ghdj\\VisitorTracker\\Events\\VisitorTracked;\n\n// In EventServiceProvider or using Event facade\nEvent::listen(VisitorTracked::class, function (VisitorTracked $event) {\n    $visitor = $event-\u003evisitor;\n    $visit = $event-\u003evisit;\n    \n    // Custom logic here\n    logger(\"New visit from {$visitor-\u003eip} to {$visit-\u003epath}\");\n});\n```\n\n### Artisan Commands\n\n```bash\n# Show visitor statistics\nphp artisan visitor-tracker:stats\nphp artisan visitor-tracker:stats --detailed\n\n# Prune old data\nphp artisan visitor-tracker:prune\nphp artisan visitor-tracker:prune --days=30\nphp artisan visitor-tracker:prune --force\n```\n\n### Scheduling Data Pruning\n\nAdd to your `routes/console.php` or scheduler:\n\n```php\nuse Illuminate\\Support\\Facades\\Schedule;\n\nSchedule::command('visitor-tracker:prune --force')-\u003edaily();\n```\n\n## Behind a Reverse Proxy / CDN\n\nIf your app sits behind Cloudflare, AWS ALB, nginx, or any other reverse proxy,\nyou **must** configure Laravel's `TrustProxies` middleware **before** enabling\nvisitor tracking. Without it, every request will appear to come from the proxy's\nIP address — breaking IP exclusions, geolocation accuracy, and IP anonymization.\n\nFor Laravel 11/12, in `bootstrap/app.php`:\n\n```php\n-\u003ewithMiddleware(function (Middleware $middleware) {\n    $middleware-\u003etrustProxies(at: '*'); // Or a specific list of proxy IPs\n})\n```\n\nFor Laravel 10, see `app/Http/Middleware/TrustProxies.php`.\n\n\u003e **Tip:** trust only the proxies you actually own. Setting `at: '*'` accepts\n\u003e any `X-Forwarded-For` header, which is fine when only your proxy can reach\n\u003e the app, but unsafe if the app is also directly accessible.\n\n## Dashboard Authentication\n\n\u003e **Security:** When `dashboard.enabled` is `true`, the package will refuse to\n\u003e boot unless at least one of `dashboard.token`, `dashboard.gate`, or an `auth*`\n\u003e entry in `dashboard.middleware` is configured. The check is auto-skipped in\n\u003e the `testing` environment so your test suite can exercise the controller\n\u003e directly. To bypass it intentionally elsewhere (e.g. you front the dashboard\n\u003e with a network-level access control), set\n\u003e `visitor-tracker.dashboard.allow_unprotected = true`.\n\n\nThe dashboard is **always protected**. Choose an authentication method based on your site:\n\n### Option 1: Token Authentication (Sites Without Login)\n\nFor sites without user authentication, use a secret token:\n\n```env\n# Add to your .env file (NEVER commit this!)\nVISITOR_TRACKER_TOKEN=your-secret-token-here\n```\n\nEnable the dashboard in `config/visitor-tracker.php`:\n\n```php\n'dashboard' =\u003e [\n    'enabled' =\u003e true,\n    'token' =\u003e env('VISITOR_TRACKER_TOKEN'),\n    'middleware' =\u003e ['web'], // No 'auth' needed\n],\n```\n\nAccess the dashboard via:\n- **URL**: `/admin/visitor-tracker?token=your-secret-token-here`\n- **Header**: `X-Visitor-Tracker-Token: your-secret-token-here`\n- **Bearer**: `Authorization: Bearer your-secret-token-here`\n\n### Option 2: Laravel Auth (Sites With Login)\n\nFor sites with user authentication:\n\n```php\n'dashboard' =\u003e [\n    'enabled' =\u003e true,\n    'middleware' =\u003e ['web', 'auth'],\n],\n```\n\n### Option 3: Gate Authorization (Role-Based Access)\n\nFor admin-only access with Laravel Gates:\n\n```php\n// In AuthServiceProvider\nGate::define('view-visitor-stats', function ($user) {\n    return $user-\u003eis_admin;\n});\n\n// In config/visitor-tracker.php\n'dashboard' =\u003e [\n    'enabled' =\u003e true,\n    'middleware' =\u003e ['web', 'auth'],\n    'gate' =\u003e 'view-visitor-stats',\n],\n```\n\n## Geolocation Providers\n\nAll providers use Laravel's built-in HTTP client - no external packages required.\n\n### ip-api.com (Free, No API Key)\n\n```env\nVISITOR_TRACKER_GEOLOCATION=true\nVISITOR_TRACKER_GEO_PROVIDER=ip-api\n```\n\n### ipinfo.io\n\n```env\nVISITOR_TRACKER_GEOLOCATION=true\nVISITOR_TRACKER_GEO_PROVIDER=ipinfo\nVISITOR_TRACKER_GEO_API_KEY=your_api_key\n```\n\n## Queue Support\n\nFor high-traffic sites, enable queue processing:\n\n```env\nVISITOR_TRACKER_QUEUE=true\nVISITOR_TRACKER_QUEUE_CONNECTION=redis\nVISITOR_TRACKER_QUEUE_NAME=tracking\n```\n\n## GDPR Safe Mode\n\nTo track **anonymous aggregate statistics without requiring user consent**, enable GDPR Safe Mode:\n\n```env\nVISITOR_TRACKER_GDPR_SAFE=true\n```\n\nWhen enabled, the following personal data is **NOT collected**:\n\n| Data | Status | Notes |\n|------|--------|-------|\n| IP Address | ❌ Not stored | Not even anonymized |\n| User ID | ❌ Not stored | No link to authenticated users |\n| Persistent Cookie | ❌ Not used | Session-only identification |\n| Full User Agent | ❌ Not stored | Only parsed for aggregate stats |\n| City / Region | ❌ Not stored | Only country-level location |\n| Coordinates | ❌ Not stored | No lat/long |\n\n\u003e **Note on session fallback:** GDPR Safe Mode identifies visitors by Laravel's\n\u003e session ID (which lives in a session cookie that expires when the browser closes\n\u003e if you set `SESSION_LIFETIME` accordingly). If the request has no session\n\u003e available at all, the tracker falls back to a daily hash of the User-Agent\n\u003e string for aggregate counting only — this is not individually identifying but\n\u003e does group same-UA requests within a single calendar day. To get the strongest\n\u003e guarantees, ensure your tracked routes go through the `web` middleware group.\n\n**What IS still collected** (anonymous, aggregate data):\n\n| Data | Purpose |\n|------|---------|\n| Page view counts | Traffic analytics |\n| Browser name | Chrome, Firefox, etc. |\n| Platform name | Windows, macOS, etc. |\n| Device type | Mobile, desktop, tablet |\n| Country | Broad geographic distribution |\n| Referrer domain | Traffic sources |\n\n```php\n// Check if GDPR safe mode is enabled\nif (VisitorTracker::isGdprSafeMode()) {\n    // No personal data being collected\n}\n```\n\n## Detected Browsers\n\nChrome, Firefox, Safari, Edge, Opera, Brave, Vivaldi, Samsung Browser, UC Browser, Yandex, IE, and more.\n\n## Detected Platforms\n\nWindows (XP through 11), macOS, iOS, Android, Linux, Ubuntu, Chrome OS, FreeBSD.\n\n## Detected Bots\n\n100+ bot patterns including:\n- **Search Engines**: Google, Bing, Yahoo, DuckDuckGo, Baidu, Yandex\n- **Social Media**: Facebook, Twitter, LinkedIn, Pinterest, Slack, Discord\n- **AI/LLM**: GPTBot, ClaudeBot, Anthropic, CCBot, Perplexity\n- **SEO Tools**: Ahrefs, SEMrush, Moz, Majestic\n- **Monitoring**: UptimeRobot, Pingdom, DataDog, New Relic\n- **HTTP Clients**: cURL, Wget, Python Requests, Postman, Axios\n\n## Testing\n\n```bash\ncomposer test\n```\n\n## Code Quality\n\n```bash\n# Run code style fixer\ncomposer format\n\n# Run static analysis\ncomposer analyse\n```\n\n## Why Zero Dependencies?\n\n- **Smaller footprint** - No additional packages to install or maintain\n- **Better performance** - Native regex is fast and efficient\n- **Full control** - Easily extend patterns via configuration\n- **Security** - Less attack surface, no supply chain concerns\n- **Reliability** - Only depends on Laravel core packages\n\n## Changelog\n\nPlease see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n## License\n\nThe MIT License (MIT). Please see [License File](LICENSE) for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fghdj%2Flaravel-visitor-tracker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fghdj%2Flaravel-visitor-tracker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fghdj%2Flaravel-visitor-tracker/lists"}