Weave 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

Laravel Device Detector Laravel Package

reefki/laravel-device-detector

Laravel integration for device detection that parses user agents to identify device type (mobile, tablet, desktop), OS, browser, and bots. Access results in Blade views, middleware, or anywhere in your app to serve tailored content, redirect traffic, and improve analytics.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and publish

composer require reefki/laravel-device-detector
php artisan vendor:publish --tag=device-detector-config   # verify tag name in the provider

The service provider is auto-discovered; you should get a config/device-detector.php and a facade (typically Reefki\DeviceDetector\Facades\DeviceDetector). Read that config file first — it is where caching, bot handling, and any UA-version truncation options live.

First use case: branch the response on device type

The 80% use case is "serve the mobile layout / block scrapers / tag analytics" — a single parse per request:

use Reefki\DeviceDetector\Facades\DeviceDetector;

$ua     = request()->userAgent();
$device = DeviceDetector::parse($ua);   // wrapper handles Matomo's setUserAgent + parse

if ($device->isBot()) {
    // don't count it, don't personalize for it
} elseif ($device->isMobile()) {
    return view('home.mobile');
}

return view('home.desktop');

The object you get back is (or proxies) Matomo's DeviceDetector, so the day-to-day getters are:

$device->getDeviceName();     // 'smartphone', 'tablet', 'desktop', ...
$device->getBrandName();      // 'Apple', 'Samsung', ...
$device->getModel();          // 'iPhone', may be empty
$device->getOs();             // ['name' => 'iOS', 'short_name' => 'iOS', 'version' => '17.4', ...]
$device->getClient();         // ['name' => 'Mobile Safari', 'short_name' => 'MF', 'version' => ..., 'engine' => ...]
$device->isTablet(); $device->isDesktop(); $device->isTouchEnabled();

Where to look next: Matomo's device-detector README. This wrapper is thin — most of your questions are answered by the upstream library, not the package.

Implementation Patterns

1. Middleware that parses once per request

UA parsing is regex-heavy; never parse twice. Resolve it once and stash it:

// app/Http/Middleware/DetectDevice.php
public function handle(Request $request, Closure $next)
{
    $device = DeviceDetector::parse($request->userAgent());

    $request->attributes->set('device', $device);
    View::share('isMobile', $device->isMobile());
    View::share('deviceType', $device->getDeviceName());

    return $next($request);
}

Then in any controller: $request->attributes->get('device'), and in Blade: @if($isMobile).

2. Request macro for readable controllers

// AppServiceProvider::boot()
Request::macro('device', fn () => $this->attributes->get('device'));
Request::macro('isMobileRequest', fn () => $this->device()?->isMobile() ?? false);

3. Cache by User-Agent string

If a request can hit the detector on multiple code paths (middleware + analytics job + Blade component), key a cache on a hash of the UA:

$key = 'ua:' . md5($ua);
$payload = Cache::remember($key, now()->addDay(), function () use ($ua) {
    $d = DeviceDetector::parse($ua);

    return [
        'type'    => $d->getDeviceName(),
        'brand'   => $d->getBrandName(),
        'model'   => $d->getModel(),
        'os'      => $d->getOs(),
        'client'  => $d->getClient(),
        'is_bot'  => $d->isBot(),
    ];
});

Cache the serializable array, not the detector object — regex/rule state doesn't serialize cleanly and you don't want it in Redis.

4. Persist device context on models

For logins, orders, and support tickets, store a small schema rather than a blob:

$table->string('device_type')->nullable();
$table->string('device_brand')->nullable();
$table->string('device_model')->nullable();
$table->string('os_name')->nullable();
$table->string('os_version')->nullable();
$table->string('client_name')->nullable();

This lets you query "how many iOS 17 users hit the checkout bug?" — far more useful than a raw UA column.

5. Analytics and bot hygiene

Use isBot() + getBot() to filter traffic in your own dashboards, or to serve a cheaper response to crawlers. This is also the correct place to not run personalization: bots should get the desktop, non-personalized variant.

6. Feature tests

Don't guess from a real browser; set the header explicitly:

$this->withHeader('User-Agent', 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_4 like Mac OS X) ...')
     ->get('/')
     ->assertViewIs('home.mobile');

Keep a small fixture list: iPhone, iPad, Android phone, desktop Chrome, Googlebot, empty UA.

7. Queues, commands, and APIs

There is no request context in a job. Always pass the UA string into the job and call parse($ua) explicitly — don't rely on the facade reading request().

Gotchas and Tips

  • User-Agent is attacker-controlled. Never use this package for authorization, rate-limit bypass decisions, or "mobile-only" security boundaries. It is a hint for UX and analytics, nothing more.
  • Parse order matters. With the raw Matomo object you must call parse() before any getter, or you get unknown/empty results. Confirm whether your facade version auto-parses; if you're ever binding the underlying class yourself, this is the #1 source of "it returns nothing" bugs.
  • Version strings are arrays. getOs()['version'] can be ''; getClient()['name'] is the long form, short_name is what you usually want for compact UI. Guard with ?? null.
  • getModel() is frequently empty. Matomo's model database is broad but not exhaustive; always fall back to brand → device type → "unknown". Don't render "Your null" in an email.
  • Config caching. After editing config/device-detector.php in production, run php artisan config:cache. If detection behavior "changes after deploy," this is usually why.
  • Octane / long-lived workers. If the facade is a singleton holding parsed state, a worker can leak one user's UA into the next request. Test under Octane explicitly, and if needed, scope-bind or reset the facade per request. This is the most likely production surprise for a small, thin wrapper.
  • Performance. The full ruleset is large. Keep the detector out of hot loops and Blade partials; one parse per request + a UA-keyed cache is the right shape. Opcache helps the first-hit cost.
  • Client Hints will erode UA fidelity. Chrome already freezes/truncates UA strings. For anything important (e.g. "is this a tablet?"), treat the detector as one signal and pair critical layout decisions with CSS/responsive checks rather than server-side branching only.
  • Spoofing and bots pretending to be browsers. isBot() catches declared crawlers; a scraper with a fake Chrome UA will look like Chrome. Combine with rate limiting if abuse is the concern.
  • Extension point. Matomo's detector supports custom client/device parsers (addClientParser, prependDeviceParser etc.). If you have an embedded webview or an internal app with a custom UA, register a parser rather than string-matching str_contains($ua, ...) in your controllers.
  • Small ecosystem (31 stars, 0 dependents). Read the provider and facade source — it's a few hundred lines. Pin the version in composer.json, and be prepared to call the underlying matomo/device-detector directly if the wrapper lags a Laravel major.
  • Debugging tip. When a UA classifies unexpectedly, instantiate Matomo's detector directly in php artisan tinker with the same string and compare. If both agree, the UA is genuinely ambiguous, not a wrapper bug.
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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings