PHP code example of rpillz / laravel-visitor
1. Go to this page and download the library: Download rpillz/laravel-visitor library . Choose the download type require .
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
rpillz / laravel-visitor example snippets
// config/database.php
'visitor' => [
'driver' => 'sqlite',
'database' => storage_path('app/analytics.sqlite'),
],
// config/database.php
'visitor_remote' => [
'driver' => 'libsql',
'url' => env('VISITOR_DB_URL'),
'authToken' => env('VISITOR_DB_AUTH_TOKEN'),
'prefix' => '',
],
// config/visitor.php
'auto_track' => false,
// routes/web.php
Route::middleware('visitor.track')->group(function () {
Route::get('/', HomeController::class);
// ...
});
use RPillz\LaravelVisitor\Facades\Visitor;
Visitor::track($request);
Visitor::anonymous()->track($request);
'anonymous' => false,
// AppServiceProvider::boot()
use RPillz\LaravelVisitor\LaravelVisitor;
LaravelVisitor::resolveConnectionUsing(function () {
return tenant() ? 'tenant_' . tenant()->id : config('visitor.connection', 'visitor');
});
Visitor::setConnection('tenant_42')->track($request);
// routes/console.php
Schedule::command('visitor:prune')->daily();
'block_probes' => true, // set false to disable entirely
'probe_paths' => [
'wp-admin*',
'wp-login*',
'.env*',
'phpinfo*',
'xmlrpc.php',
// add your own patterns — supports * and ? wildcards
],
'probe_block_duration' => env('VISITOR_PROBE_BLOCK_DURATION', 60*24*3), // minutes, null = permanent
'probe_404' => [
'threshold' => env('VISITOR_PROBE_404_THRESHOLD', 5), // 404s before blocking
'window' => env('VISITOR_PROBE_404_WINDOW', 3), // rolling window in minutes
],
'verified_crawlers' => [
'enabled' => env('VISITOR_VERIFIED_CRAWLERS', true),
'cache_ttl' => env('VISITOR_CRAWLER_CACHE_TTL', 1440), // minutes per IP
'ip_lists' => [
'https://raw.githubusercontent.com/hexydec/ip-ranges/main/output/crawlers.json',
],
],
// Blocked by name, even if IP-verified
'block_verified_bots' => [
'ClaudeBot', 'GPTBot', 'PerplexityBot', 'Amazonbot', 'CCBot', 'Bytespider',
'Meta-WebIndexer', 'Meta-ExternalAds', 'Meta-ExternalAgent',
'Semrush', 'Ahrefs', 'DotBot', 'MJ12bot', 'Diffbot', 'PetalBot', 'Scrapy',
],
// Block any crawler that cannot prove its identity (default: true)
'block_unverified_bots' => env('VISITOR_BLOCK_UNVERIFIED_BOTS', true),
'allow_agents' => [
'Phare', // Phare uptime monitor
'UptimeRobot', // UptimeRobot
],
'rate_limit' => [
'enabled' => env('VISITOR_RATE_LIMIT', true),
'threshold' => env('VISITOR_RATE_LIMIT_THRESHOLD', 60), // requests per window
'window' => env('VISITOR_RATE_LIMIT_WINDOW', 1), // minutes
'auto_block' => env('VISITOR_RATE_LIMIT_AUTO_BLOCK', true),
],
'robots_txt' => [
'enabled' => env('VISITOR_ROBOTS_TXT', false),
'disallow' => [
'ClaudeBot', 'Amazonbot', 'meta-externalagent',
'meta-webindexer', 'meta-externalads',
'GPTBot', 'Google-Extended', 'PerplexityBot', 'CCBot',
],
],
'log_blocks' => env('VISITOR_LOG_BLOCKS', true),
use RPillz\LaravelVisitor\Filament\VisitorPlugin;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->plugins([
VisitorPlugin::make(),
]);
}
> 'silenced' => [
> \RPillz\LaravelVisitor\Jobs\TrackVisitJob::class,
> ],
>
// config/visitor.php
return [
// Database connection for visit records
'connection' => env('VISITOR_DB_CONNECTION', 'visitor'),
// Queue connection and name for the tracking job
'queue' => [
'connection' => env('VISITOR_QUEUE_CONNECTION', null),
'name' => env('VISITOR_QUEUE_NAME', 'default'),
],
// Automatically append visitor.track to the web middleware group
'auto_track' => env('VISITOR_AUTO_TRACK', true),
// Paths to exclude from tracking (supports * and ? wildcards)
'exclude_paths' => [
'admin*', '_debugbar*', 'horizon*', 'telescope*', 'livewire*', '_ignition*',
],
// Track bot/crawler visits (stores bot_name, fingerprint, is_verified)
'track_bots' => env('VISITOR_TRACK_BOTS', true),
// Skip requests from these IPs
'exclude_ips' => [],
// Only track these HTTP methods
'track_methods' => ['GET'],
// Never store the authenticated user ID
'anonymous' => true,
// Never store IP addresses (also skips country/city resolution)
'store_ip' => env('VISITOR_STORE_IP', false),
// Prevent duplicate records for the same session+path within a rolling window
'deduplication' => [
'enabled' => env('VISITOR_DEDUP_ENABLED', true),
'window' => env('VISITOR_DEDUP_WINDOW', 30), // minutes
],
// Local MaxMind GeoLite2 database for country/city resolution (disabled by default)
'geoip' => [
'enabled' => env('VISITOR_GEOIP_ENABLED', false),
'database' => env('VISITOR_GEOIP_DATABASE', storage_path('app/geoip/GeoLite2-City.mmdb')),
],
// Bot names (resolved from User-Agent) to block even when IP-verified
'block_verified_bots' => [
'ClaudeBot', 'GPTBot', 'PerplexityBot', 'Amazonbot', 'CCBot', 'Bytespider',
'Meta-WebIndexer', 'Meta-ExternalAds', 'Meta-ExternalAgent',
'Semrush', 'Ahrefs', 'DotBot', 'MJ12bot', 'Diffbot', 'PetalBot', 'Scrapy',
],
// Block any crawler that cannot be verified via rDNS or a published IP list
'block_unverified_bots' => env('VISITOR_BLOCK_UNVERIFIED_BOTS', true),
// User-Agent substrings that bypass block_verified_bots and block_unverified_bots
'allow_agents' => [
// 'Phare',
],
// Fingerprint-based rate limiter — catches high-volume scrapers that hit only valid pages
'rate_limit' => [
'enabled' => env('VISITOR_RATE_LIMIT', true),
'threshold' => env('VISITOR_RATE_LIMIT_THRESHOLD', 60), // requests per window
'window' => env('VISITOR_RATE_LIMIT_WINDOW', 1), // minutes
'auto_block' => env('VISITOR_RATE_LIMIT_AUTO_BLOCK', true),
],
// Serve GET /robots.txt with Disallow entries for each listed User-agent
'robots_txt' => [
'enabled' => env('VISITOR_ROBOTS_TXT', false),
'disallow' => [
'ClaudeBot', 'Amazonbot', 'meta-externalagent',
'meta-webindexer', 'meta-externalads',
'GPTBot', 'Google-Extended', 'PerplexityBot', 'CCBot',
],
],
// Auto-block IPs and fingerprints that hit probe paths; return 404
'block_probes' => env('VISITOR_BLOCK_PROBES', true),
// Record blocked requests as visits with is_blocked=true (excluded from analytics)
'log_blocks' => env('VISITOR_LOG_BLOCKS', true),
// Paths treated as probe/scanner activity (supports wildcards)
'probe_paths' => [
'wp-admin*', 'wp-login*', '.env*', 'phpinfo*', 'xmlrpc.php',
],
// How long auto-blocks last (minutes); null = permanent
'probe_block_duration' => env('VISITOR_PROBE_BLOCK_DURATION', 60 * 24 * 3), // 3 days
// Auto-block IPs that hit this many 404s within the window
'probe_404' => [
'threshold' => env('VISITOR_PROBE_404_THRESHOLD', 5),
'window' => env('VISITOR_PROBE_404_WINDOW', 3), // minutes
],
// Verify legitimate search engine bots via rDNS and published IP lists
'verified_crawlers' => [
'enabled' => env('VISITOR_VERIFIED_CRAWLERS', true),
'cache_ttl' => env('VISITOR_CRAWLER_CACHE_TTL', 1440), // minutes per IP
'ip_lists' => [
'https://raw.githubusercontent.com/hexydec/ip-ranges/main/output/crawlers.json',
],
],
// Retention period for visit records
'pruning' => [
'enabled' => true,
'days' => env('VISITOR_PRUNE_DAYS', 90),
],
];
// config/visitor.php
'anonymous' => false,
'store_ip' => true,
Artisan::call('visitor:forget', ['userId' => $user->id, '--force' => true]);
// config/visitor.php
'pruning' => ['enabled' => true, 'days' => 90],
// routes/console.php
Schedule::command('visitor:prune')->daily();
bash
php artisan visitor:install
bash
php artisan vendor:publish --tag="visitor-config"
php artisan vendor:publish --tag="visitor-migrations"
php artisan migrate
bash
php artisan visitor:prune --days=90
bash
# By user ID
php artisan visitor:forget {userId}
# By session ID (for anonymous visitors)
php artisan visitor:forget --session={sessionId}
# By IP address
php artisan visitor:forget --ip={ipAddress}