Weave Code
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

Visitor Laravel Package

shetabit/visitor

Track and log Laravel visitor info (IP, browser, device, platform, languages, user agent) via request helper, and attach visit logs to models with a Visitable trait. Includes online user detection and visit counting/uniques by IP or user.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require shetabit/visitor
    php artisan vendor:publish --provider="Shetabit\Visitor\Provider\VisitorServiceProvider"
    php artisan migrate
    

    (Laravel 5.5+ auto-registers the service provider; no manual registration needed.)

  2. First Use Case: Access visitor data in a controller:

    use Illuminate\Http\Request;
    
    public function show(Request $request) {
        $browser = $request->visitor()->browser(); // e.g., "Chrome"
        $ip = $request->visitor()->ip(); // e.g., "192.168.1.1"
        return response()->json(['visitor' => compact('browser', 'ip')]);
    }
    
  3. Key Entry Points:

    • Facade: visitor()->browser() (global access).
    • Request Macro: $request->visitor()->device() (controller-specific).
    • Helper: visitor()->isOnline($user) (blade/views).

Implementation Patterns

1. Model Visit Tracking

Workflow:

  • Add Visitable trait to models (e.g., Post, Product):
    use Shetabit\Visitor\Traits\Visitable;
    
    class Post extends Model {
        use Visitable;
    }
    
  • Log visits in controllers/middleware:
    // Option 1: Automatic (via LogVisits middleware)
    Route::middleware(['logVisits'])->group(function () {
        Route::get('/posts/{post}', [PostController::class, 'show']);
    });
    
    // Option 2: Manual
    $post->createVisitLog($user); // Associate with a user
    visitor()->visit($post); // Anonymous visit
    

Integration Tips:

  • Exclude Routes: Configure in config/visitor.php:
    'except' => [
        'admin/*',
        'api/webhooks/*',
    ],
    
  • Batch Logging: Use queues for high-traffic models:
    $post->createVisitLog($user)->dispatch();
    

2. Online User Detection

Workflow:

  • Add Visitor trait to your User model:
    use Shetabit\Visitor\Traits\Visitor;
    
    class User extends Authenticatable {
        use Visitor;
    }
    
  • Query online users:
    // Global online users
    $onlineUsers = visitor()->onlineVisitors(User::class);
    
    // Model-specific (e.g., users viewing a Post)
    $post->visits()->with('visitor')->get();
    

Patterns:

  • Real-Time Features:
    // Live collaboration
    if ($user->isOnline()) {
        broadcast(new UserActive($user));
    }
    
  • Admin Dashboards:
    $activeUsers = User::online()->take(10)->get();
    

3. GeoIP Enrichment (Optional)

Setup:

  1. Install dependencies:
    composer require geoip2/geoip2
    
  2. Configure in .env:
    VISITOR_GEOIP_ENABLED=true
    VISITOR_GEOIP_DATABASE=/path/to/GeoLite2-City.mmdb
    
  3. Access data:
    $visit = $post->visits()->latest()->first();
    $country = $visit->geoip?->country->isoCode; // e.g., "US"
    

4. Middleware Integration

Use Cases:

  • Automatic Logging: Apply LogVisits to routes/models:
    Route::middleware(['logVisits'])->group(function () {
        Route::resource('posts', PostController::class);
    });
    
  • Exclude Sensitive Routes: Configure in config/visitor.php:
    'except' => [
        'password/reset',
        'api/orders',
    ],
    

Gotchas and Tips

Pitfalls

  1. Database Overhead:

    • Issue: High-traffic models (e.g., Product) may slow down with frequent visit() calls.
    • Fix: Use queues or batch logging:
      $post->visits()->create([...])->dispatch();
      
  2. IP Deduplication:

    • Issue: distinct('ip') may not work as expected if IPs are hashed.
    • Fix: Ensure ip column is stored raw in migrations:
      $table->string('ip')->nullable();
      
  3. GeoIP Performance:

    • Issue: GeoIP lookups add ~50–100ms latency.
    • Fix: Cache results:
      $visit->geoip = Cache::remember("geoip_{$visit->ip}", now()->addHours(1), function () {
          return geoip($visit->ip);
      });
      
  4. Middleware Conflicts:

    • Issue: LogVisits may interfere with auth middleware.
    • Fix: Order matters in $middlewareGroups:
      'web' => [
          \App\Http\Middleware\Authenticate::class,
          \Shetabit\Visitor\Middlewares\LogVisits::class, // After auth
      ],
      

Debugging Tips

  1. Visitor Data:

    • Dump raw data:
      dd($request->visitor()->toArray());
      
    • Check useragent parsing:
      dd($request->userAgent());
      
  2. Online Status:

    • Verify session lifetime in config/visitor.php:
      'online_timeout' => 30, // minutes
      
    • Debug with:
      dd(visitor()->isOnline($user)); // Returns bool
      
  3. Logs:

    • Inspect raw logs:
      $post->visits()->with('visitor')->latest()->take(5)->get();
      
    • Filter by IP/user:
      $post->visits()->where('ip', $ip)->count();
      

Extension Points

  1. Custom Visitor Attributes:

    • Extend the Visitor class:
      class CustomVisitor extends \Shetabit\Visitor\Visitor {
          public function isMobileApp() {
              return str_contains($this->useragent, 'MobileApp/');
          }
      }
      
    • Bind in AppServiceProvider:
      Visitor::macro('isMobileApp', function () {
          return $this->isMobileApp();
      });
      
  2. GeoIP Providers:

    • Swap implementations:
      // config/visitor.php
      'geoip' => [
          'driver' => 'custom',
          'custom' => \App\Services\CustomGeoIP::class,
      ],
      
  3. Visit Logs:

    • Add custom fields to migrations:
      Schema::table('visits', function (Blueprint $table) {
          $table->string('utm_source')->nullable();
      });
      
    • Update the visit() method:
      $post->createVisitLog($user, [
          'utm_source' => $request->input('utm_source'),
      ]);
      

Pro Tips

  1. Anonymize Data for Compliance:

    • Hash IPs in migrations:
      $table->string('ip_hash')->unique();
      
    • Use a mutator:
      public function setIpAttribute($value) {
          $this->attributes['ip_hash'] = hash('sha256', $value);
      }
      
  2. Performance Optimization:

    • Disable logging for bots:
      if ($request->visitor()->isBot()) {
          return response()->json(['error' => 'Blocked']);
      }
      
    • Use remember() for frequent queries:
      $post->visits()->remember(60)->count();
      
  3. Testing:

    • Mock visitor data:
      $request->shouldReceive('visitor')->andReturn(
          Visitor::fake()->browser('Firefox')->ip('192.168.1.1')
      );
      
    • Test online status:
      $user->shouldReceive('isOnline')->andReturn(true);
      
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.
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament