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

Device Detector Laravel Package

matomo/device-detector

Parses User-Agent strings and browser Client Hints to identify device type (desktop/tablet/mobile/TV/console), client apps (browsers, media players, feed readers), operating systems, and device brand/model. Composer-ready PHP library.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require matomo/device-detector
    

    Add to composer.json under require or require-dev if only for testing.

  2. First Use Case: Parse the current request's user agent in a Laravel controller or middleware:

    use DeviceDetector\DeviceDetector;
    use DeviceDetector\ClientHints;
    
    $userAgent = request()->userAgent();
    $clientHints = ClientHints::factory($_SERVER);
    $dd = new DeviceDetector($userAgent, $clientHints);
    $dd->parse();
    
    // Basic checks
    if ($dd->isMobile()) {
        return response()->json(['device' => 'mobile']);
    }
    
  3. Where to Look First:

    • Documentation: GitHub README for API reference.
    • Laravel Integration: Focus on DeviceDetector\Cache\LaravelCache for caching.
    • Examples: Check the Usage section in the README for common patterns.

Implementation Patterns

Core Workflows

  1. Request Parsing in Middleware: Create a middleware to parse and store device data in the request object:

    namespace App\Http\Middleware;
    
    use Closure;
    use DeviceDetector\DeviceDetector;
    use DeviceDetector\ClientHints;
    
    class DetectDevice
    {
        public function handle($request, Closure $next)
        {
            $userAgent = $request->userAgent();
            $clientHints = ClientHints::factory($_SERVER);
            $dd = new DeviceDetector($userAgent, $clientHints);
            $dd->parse();
    
            $request->merge([
                'device' => $dd->getDeviceName(),
                'is_mobile' => $dd->isMobile(),
                'is_tablet' => $dd->isTablet(),
                'client' => $dd->getClient(),
                'os' => $dd->getOs(),
            ]);
    
            return $next($request);
        }
    }
    

    Register in app/Http/Kernel.php:

    protected $middleware = [
        \App\Http\Middleware\DetectDevice::class,
    ];
    
  2. Caching Strategies:

    • Laravel Cache: Use the built-in bridge for request-level caching:
      $dd->setCache(new \DeviceDetector\Cache\LaravelCache());
      
    • PSR-6 Cache: For shared caching (e.g., Redis):
      $cache = Cache::store('redis');
      $dd->setCache(new \DeviceDetector\Cache\PSR6Bridge($cache));
      
  3. Conditional Logic: Use device detection to route users or modify responses:

    if (request()->is_mobile) {
        return view('mobile.home');
    }
    return view('desktop.home');
    
  4. Bot Detection: Skip bot-specific logic early:

    if ($dd->isBot()) {
        return response()->json(['status' => 'bot'], 403);
    }
    
  5. Client Hints Integration: Enable for modern browsers (requires server Accept-CH header):

    $clientHints = ClientHints::factory($_SERVER, [
        'Accept-CH' => 'Sec-CH-UA, Sec-CH-UA-Mobile',
    ]);
    

Integration Tips

  • Service Provider: Centralize DeviceDetector instantiation in a service provider for dependency injection.
  • Eloquent Scopes: Add device-based scopes to models:
    public function scopeMobile($query)
    {
        return $query->whereHas('user', function ($q) {
            $q->where('device_type', 'mobile');
        });
    }
    
  • Analytics: Log device data to Matomo or custom analytics:
    \Matomo\Tracker::getInstance('https://your.matomo.url')
        ->setUserAgent(request()->userAgent())
        ->setDevice(request()->device)
        ->doTrackPageView();
    

Gotchas and Tips

Pitfalls

  1. User Agent Spoofing:

    • User agents can be faked. Validate with additional signals (e.g., Sec-CH-UA headers) when possible.
    • Example:
      if ($dd->getClient('name') === 'Chrome' && !$dd->isMobile()) {
          // Likely a desktop Chrome, but could be spoofed.
      }
      
  2. Performance Overhead:

    • Parsing without caching is slow. Always configure caching:
      $dd->setCache(new \DeviceDetector\Cache\LaravelCache());
      
    • Avoid parsing in loops or high-frequency contexts (e.g., API rate-limiting checks).
  3. Client Hints Limitations:

    • Not all browsers support Accept-CH. Fall back to user agent parsing:
      if (!$clientHints->isSupported()) {
          $dd = new DeviceDetector($userAgent);
      }
      
  4. Version Truncation:

    • Default behavior truncates versions (e.g., 12.3.412.3). Disable if full versions are needed:
      use DeviceDetector\Parser\Device\AbstractDeviceParser;
      AbstractDeviceParser::setVersionTruncation(AbstractDeviceParser::VERSION_TRUNCATION_NONE);
      
  5. Bot Detection Edge Cases:

    • Some bots mimic user agents. Use discardBotInformation() for performance if bots are irrelevant:
      $dd->discardBotInformation();
      

Debugging

  • Log User Agents: Log raw user agents for debugging:
    \Log::debug('User Agent:', [$userAgent]);
    
  • Test with Known Agents: Use tools like UserAgentString.com to test edge cases:
    $dd = new DeviceDetector('Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) ...');
    

Extension Points

  1. Custom YAML Parser: Override the default Spyc parser for Symfony/YAML:

    $dd->setYamlParser(new \DeviceDetector\Yaml\Symfony());
    
  2. Custom Cache: Implement DeviceDetector\Cache\CacheInterface for bespoke storage:

    class MyCache implements CacheInterface {
        public function get($key) { ... }
        public function set($key, $value, $ttl = null) { ... }
    }
    $dd->setCache(new MyCache());
    
  3. Update Rules: Manually update detection rules (located in vendor/matomo/device-detector/DeviceDetector/Parser/) if new devices/browsers are missing. Contribute upstream!

  4. Laravel Service Container: Bind DeviceDetector to the container for easy access:

    $this->app->singleton(DeviceDetector::class, function ($app) {
        $userAgent = request()->userAgent();
        $clientHints = ClientHints::factory($_SERVER);
        $dd = new DeviceDetector($userAgent, $clientHints);
        $dd->setCache(new \DeviceDetector\Cache\LaravelCache());
        return $dd;
    });
    

    Then inject via constructor:

    public function __construct(private DeviceDetector $dd) {}
    

Tips

  • Leverage Laravel Helpers: Combine with Laravel's request() helpers for cleaner code:
    $isMobile = request()->device->isMobile();
    
  • Environment-Specific Config: Disable bot detection in production if irrelevant:
    if (app()->environment('production')) {
        $dd->skipBotDetection();
    }
    
  • Monitor False Positives: Track misclassified devices in logs and update rules as needed:
    if ($dd->getDeviceName() === 'Unknown') {
        \Log::warning('Unknown device detected:', [$userAgent]);
    }
    
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.
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi