PHPackages                             ondrej-vrto/laravel-visitors - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. ondrej-vrto/laravel-visitors

ActiveLibrary[Database &amp; ORM](/categories/database)

ondrej-vrto/laravel-visitors
============================

Laravel package that allows you to associate views with Eloquent models and create traffic and statistics.

0.3.2(3y ago)141[2 PRs](https://github.com/OndrejVrto/laravel-visitors/pulls)MITPHPPHP ^8.1|^8.2

Since Jan 24Pushed 2y ago1 watchersCompare

[ Source](https://github.com/OndrejVrto/laravel-visitors)[ Packagist](https://packagist.org/packages/ondrej-vrto/laravel-visitors)[ Docs](https://github.com/OndrejVrto/laravel-visitors)[ GitHub Sponsors](https://github.com/OndrejVrto)[ RSS](/packages/ondrej-vrto-laravel-visitors/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (4)Dependencies (24)Versions (8)Used By (0)

[![Social Card of PHP Line Chart](./.github/img/socialcard.png)](./.github/img/socialcard.png)

A Laravel package that allows you to track Eloquent model traffic.
==================================================================

[](#a-laravel-package-that-allows-you-to-track-eloquent-model-traffic)

[![Latest Version on Packagist](https://camo.githubusercontent.com/c77c4e4d642ac9eb3811cfdd525579cddcbeaccc1fadc328b3b61dd41cbbb192/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6f6e6472656a2d7672746f2f6c61726176656c2d76697369746f72732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/ondrej-vrto/laravel-visitors)[![Tests](https://camo.githubusercontent.com/c82d46eb8107b84fc3b0372e5941d0cff4464aa41dc3518f3857242549f54608/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f4f6e6472656a5672746f2f6c61726176656c2d76697369746f72732f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/OndrejVrto/laravel-visitors/blob/main/.github/workflows/run-tests.yml)[![Total Downloads](https://camo.githubusercontent.com/7fe3409b707834f16da44d804027f7a58b10671adc6807fe24a6c384bbd3c4f5/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6f6e6472656a2d7672746f2f6c61726176656c2d76697369746f72732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/ondrej-vrto/laravel-visitors)

Prologue
--------

[](#prologue)

This tool enables basic monitoring of user activity without the use of cookies or consent according to the European GDPR guidelines. It creates overall statistics, which take a long time to generate, in the background, and therefore displaying results even in large volumes of data is fast.

Installation
------------

[](#installation)

You can install the package via composer:

```
composer require ondrej-vrto/laravel-visitors
```

### Publish

[](#publish)

```
php artisan vendor:publish --provider="OndrejVrto\Visitors\VisitorsServiceProvider"
# or separately
php artisan vendor:publish --tag=visitors-config
php artisan vendor:publish --tag=visitors-migrations
php artisan vendor:publish --tag=visitors-translations
```

Basic usage visit counter
-------------------------

[](#basic-usage-visit-counter)

Apply contract "Visitable" and trait "InteractsWithVisits" to model

```
class Post extends Model implements Visitable
{
    use InteractsWithVisits;

    // Remove visits on delete model
    protected $removeDataOnDelete = true;

    // ...
}
```

Some in frontend controler add visit counter.

```
public function show()
{
    $post = Post::find(5);
    $post->incrementVisit();

    $commercial = Commercial::find(100);
    $commercial->incrementVisit();

    return view('post.show', compact('post', 'commercial'));
}
```

Basic usage display statistics
------------------------------

[](#basic-usage-display-statistics)

In dashboard

```
public function dashboard()
{
    $topTenYearVisitsByPerson = Traffic::list()
        ->visitedByPersons()
        ->orderByLast365Days()
        ->withRelationship()
        ->limit(10)
        ->get();

    $sumarAllVisitFromWeb = Traffic::summary()
        ->visitedByPersons()
        ->inCategory(VisitorCategory::WEB)
        ->first();

    $sumarAllVisitFromApi = Traffic::summary()
        ->visitedByCrawlersAndPersons()
        ->inCategory(VisitorCategory::API)
        ->first();

    return view(
        'dashboard',
        compact('topTenYearVisitsByPerson', 'sumarAllVisit', '$sumarAllVisitFromApi')
    );
}
```

Or list of posts in admin controller.

```
public function index()
{
    $posts = Post::withTraffic()->paginate(10);

    return view('post.index', compact('posts'));
}
```

Or in detail post in admin controller.

```
public function show(Post $post)
{
    $visits = Traffic::single($post)
        ->inCategory(VisitorCategory::WEB)
        ->visitedByPersons()
        ->first();

    return view('post.show', compact('post', 'visits'));
}
```

Customization visit counter
---------------------------

[](#customization-visit-counter)

Increment methods

```
// methods from model
$post->incrementVisit();
$post->incrementVisitForce();
// or with Facade
Visit::model($post)->increment();
// or with helper function
visit($post)->increment();
```

Options

```
// Check expiration time for ip address, model and category is is set
visit($post)->increment();
// Expiration time off
visit($post)->forceIncrement();

// With defining different categories for the record from Backed Enums
visit($post)->inCategory(VisitorCategory::WEB)->increment();

// Crawlers detection enabled/disabled. Rewrite config settings
visit($post)->withCrawlers()->increment();
visit($post)->withoutCrawlers()->increment();

// Rewrite default expires time
$expiresAt = now()->addHours(3); // `DateTimeInterface` instance
$expiresAt = 60; // minutes in Integer
visit($post)->expiresAt($expiresAt)->increment();

// dynamicaly create ip ignore list
visit($post)->addIpAddressToIgnoreList(['127.0.0.1', '147.7.54.789'])->increment();
```

Manually added data.

```
visit($post)
    ->fromIP('127.0.0.1')
    ->isCrawler()
    ->isPerson()
    ->inLanguage('Esperanto')
    ->fromBrowserAgent('custom browser agent string ....')
    ->fromOperatingSystem(OperatingSystem::WINDOWS)
    ->visitedAt(Carbon::now()->addMinute(5))
    ->increment();
```

Pruning models
--------------

[](#pruning-models)

***Note:*** Pruning run automaticaly before start generator statistics and trafic

```
php artisan visitors:clean
```

```
// in App\Console\Kernel
$schedule->command('model:prune')->daily();
// OR
$schedule->command('model:prune', [
    '--model' => [VisitorsData::class, VisitorsExpires::class],
])->daily();
// OR
Artisan::call("visitors:clean");
```

Generate traffic data
---------------------

[](#generate-traffic-data)

***Note:*** Queue service is required

```
php artisan visitors:fresh
```

```
// Manual in controller
Artisan::call("visitors:fresh");
// OR
(new TrafficGenerator())->run();
// Automatic in Scheduler (in App\Console\Kernel)
$schedule->command(VisitorsFreshCommand::class)->everyThreeHours();
```

Scheduler is implement in package. If is set `schedule_generate_traffic_data_automaticaly` to `true` nothing else needs to be set up.

View traffic data
-----------------

[](#view-traffic-data)

With preety graph in SVG, count of language and operating system statistics.

### Aggregated data from several models

[](#aggregated-data-from-several-models)

***Note:*** Return only one record

```
// summary global
$sumary = Traffic::summary()->first();    // with Facade
$sumary = traffic()->summary()->first();  // with helper function

// summary for all type models and all categories
$sumary = Traffic::summary()->visitedByPersons()->first();
$sumary = Traffic::summary()->visitedByCrawlers()->first();
$sumary = Traffic::summary()->visitedByCrawlersAndPersons()->first();

// summary for all type models and one category
$sumary = Traffic::summary()->inCategory(VisitorCategory::WEB)->first();

// summary for one type model and all categories
$sumary = Traffic::summary()->forModel(Post::class)->first();
$sumary = Traffic::summary()->forModel('App\Models\Post')->first();

// speciffic select
$sumary = Traffic::summary()
    ->forModel(Post::class)
    ->inCategory(VisitorCategory::WEB)
    ->visitedByCrawlersAndPersons()
    ->first();
```

### Trafic for a one specific model

[](#trafic-for-a-one-specific-model)

***Note:*** Return only one record

```
$post = Post::find(1);

// Return model instance Traffic or null
$single = Traffic::single($post)->first();    // with Facade
$single = traffic()->single($post)->first();  // with helper function

// adds relationships to the Visitable Model
$single = Traffic::single($post)->withRelationship()->first();
```

Other options similar to statistics in the previous chapter

```
// summary for one model for all categories visited by persons
$single = Traffic::single($post)->visitedByPersons()->first();

// summary for one model for one category and all bots
$single = Traffic::single($post)->inCategory(VisitorCategory::WEB)->first();

// summary for one model for one category visited only persons
$single = Traffic::single($post)
    ->inCategory(VisitorCategory::WEB)
    ->visitedByCrawlersAndPersons()
    ->first();
```

### Lists of top visit models

[](#lists-of-top-visit-models)

***Note:*** Return Collection of model instances Traffic

```
// Return Eloquent Builder
$traffic = Traffic::list();    // with Facade
$traffic = traffic()->list();  // with helper function

// Return collection, first model from collection or paginator
$traffic = Traffic::list()->get();
$traffic = Traffic::list()->first();
$traffic = Traffic::list()->paginate();

// adds relationships to the Visitable Model
$traffic = traffic()->list()->withRelationship()->get();

// only specific models type
$models = [VisitableModel::class, AnotherVisitableModel::class, "App\Models\Post"];
$traffic = Traffic::list($models)->get();
```

Other options

```
$traffic = Traffic::list($models)
    ->inCategory(VisitorCategory::WEB)
    ->inCategories([VisitorCategory::WEB, VisitorCategory::API])
    ->forModel(Post::class)
    ->addModels([Example::class])
    ->orderByTotal()
    ->orderByLastDay()
    ->orderByLast7Days()
    ->orderByLast30Days()
    ->orderByLast365Days()
    ->orderBy('column_name', 'asc')
    ->visitedByPersons()
    ->visitedByCrawlers()
    ->visitedByCrawlersAndPersons()
    ->withRelationship()
    ->limit(10)
    ->get();   //->first();   //->paginate();
```

Relationship scope for model is posible
---------------------------------------

[](#relationship-scope-for-model-is-posible)

Join all traffic data to Visitable model

```
$post = Post::find($id)->withTraffic()->first();
// all scopes
$posts = Post::query()
    ->withTraffic()
    ->orderByTotal()
    ->orderByLastDay()
    ->orderByLast7Days()
    ->orderByLast30Days()
    ->orderByLast365Days()
    ->paginate();
```

Get the status and additional data about the latest traffic generation process
------------------------------------------------------------------------------

[](#get-the-status-and-additional-data-about-the-latest-traffic-generation-process)

Displays the parameters of the last run of the generator and the difference from the current data

```
$info = Traffic::info();
```

Language
--------

[](#language)

Enum classes 'OperatingSystem' and 'VisitorCategory' are translatable.

Configuration package
---------------------

[](#configuration-package)

```
    /*
    / --------------------------------------------------------------------------
    / Eloquent settings
    / --------------------------------------------------------------------------
    /*
    / Here you can configure the table names in database.
    */

    'table_names' => [
        'info'    => 'visitors_info',
        'data'    => 'visitors_data',
        'expires' => 'visitors_expires',
        'traffic' => 'visitors_traffic',
    ],

    /*
    / --------------------------------------------------------------------------
    / Categories
    / --------------------------------------------------------------------------
    /
    / Use one of the options of the enum VisitCategory to set
    / the default category.
    /
    / Default: OndrejVrto\Visitors\Enums\VisitorCategory::UNDEFINED
    */

    'default_category' => OndrejVrto\Visitors\Enums\VisitorCategory::UNDEFINED,

    /*
    / --------------------------------------------------------------------------
    / Default expires time in minutes
    / --------------------------------------------------------------------------
    /
    / If you want set expiration time for ip adress and models in minutes.
    / Ignore this setting apply forceIncrement() method
    /
    / Default: 15
    */

    'expires_time_for_visit' => 15,

    /*
    / --------------------------------------------------------------------------
    / Ignore Bots and IP addresses
    / --------------------------------------------------------------------------
    /
    / If you want to ignore bots, you can specify that here. The default
    / service that determines if a visitor is a crawler is a package
    / by JayBizzle called CrawlerDetect.
    /
    / Default value: false
    */

    'storage_request_from_crawlers_and_bots' => false,

    /*
    / Ignore views of the following IP addresses.
    */

    'ignored_ip_addresses' => [
        // '127.0.0.1',
    ],

    /*
    / --------------------------------------------------------------------------
    / Statistics and traffic data
    / --------------------------------------------------------------------------
    /
    / The number of days after which traffic data will be deleted from today.
    / Warning: Older data will be permanently deleted.
    /
    / Value range  : 1 day - 36500 days
    / Default value: 730 (two years)
    */

    'number_days_traffic' => 730,

    /*
    / Create separate daily traffic graphs for used categories.
    /
    / Warning: Slows down data generation.
    / Default: false
    */

    'generate_traffic_for_categories' => false,

    /*
    / Create separate daily traffic graphs for crawlers and persons.
    /
    / Note   : If is set "storage_request_from_crawlers_and_bots" to true or apply withCrawlers() method.
    / Warning: Slows down data generation.
    / Default: false
    */

    'generate_traffic_for_crawlers_and_persons' => false,

    /*
    / Schedule the generation of traffic data and statistics within
    / the internal scheduler of this package. It will run every three hours.
    /
    / Note   : Equivalent to setting in the scheduler (in App\Console\Kernel)
    /          $schedule->command(VisitorsFreshCommand::class)->everyThreeHours();
    / Default: true
    */

    'schedule_generate_traffic_data_automaticaly' => true,

    /*
    / --------------------------------------------------------------------------
    / Line graphs in SVG
    / --------------------------------------------------------------------------
    /
    / Note:  https://github.com/OndrejVrto/php-linechart
    */

    'generate_graphs' => true,

    'graphs_properties' => [

        'maximum_value_lock' => null,
        'maximum_days'       => null,
        'order_reverse'      => false,
        'width_svg'          => 1000,
        'height_svg'         => 50,
        'stroke_width'       => 2,
        'colors'             => ['#4285F4', '#31ACF2', '#2BC9F4'],

    ],
```

Testing
-------

[](#testing)

```
composer test
```

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

Credits
-------

[](#credits)

- [Ondrej Vrťo](https://github.com/OndrejVrto)
- [All Contributors](../../contributors)

Alternatives
------------

[](#alternatives)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

25

—

LowBetter than 37% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity9

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity53

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 99% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~7 days

Total

4

Last Release

1183d ago

PHP version history (2 changes)0.2.0PHP ^8.1

0.3.0PHP ^8.1|^8.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/ef50ff0349871cc35df4a7d2a2d322972942cab3f1756eb79938694b6eced489?d=identicon)[OndrejVrto](/maintainers/OndrejVrto)

---

Top Contributors

[![OndrejVrto](https://avatars.githubusercontent.com/u/32365016?v=4)](https://github.com/OndrejVrto "OndrejVrto (200 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (1 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (1 commits)")

---

Tags

eloquentlaravellaravel-packagephpphp81visitor-counterphplaravelpackageeloquentcounterstatisticsvisitstrafficGraph daily visit

###  Code Quality

TestsPest

Static AnalysisPHPStan, Rector

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/ondrej-vrto-laravel-visitors/health.svg)

```
[![Health](https://phpackages.com/badges/ondrej-vrto-laravel-visitors/health.svg)](https://phpackages.com/packages/ondrej-vrto-laravel-visitors)
```

###  Alternatives

[cyrildewit/eloquent-viewable

Laravel package that allows you to associate views with Eloquent models

8831.1M6](/packages/cyrildewit-eloquent-viewable)[dyrynda/laravel-model-uuid

This package allows you to easily work with UUIDs in your Laravel models.

4802.8M8](/packages/dyrynda-laravel-model-uuid)[awssat/laravel-visits

Laravel Redis visits counter for Eloquent models

975163.6k2](/packages/awssat-laravel-visits)[reedware/laravel-relation-joins

Adds the ability to join on a relationship by name.

2121.2M13](/packages/reedware-laravel-relation-joins)[io238/laravel-iso-countries

Ready-to-use Laravel models and relations for country (ISO 3166), language (ISO 639-1), and currency (ISO 4217) information with multi-language support.

5462.3k](/packages/io238-laravel-iso-countries)[lacodix/laravel-model-filter

A Laravel package to filter, search and sort models with ease while fetching from database.

17649.9k](/packages/lacodix-laravel-model-filter)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
