NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
Packagist · #3537 most downloaded on Packagist
A minimalistic analytics package for Laravel with seamless view tracking for Eloquent models
Last release 8 days ago
30 Sep 2026
Release timing varies
gaps range from 2 weeks to 1.2 years
Most releases are documented
notes for 35 of 49 stable releases
Nothing withdrawn
no release was ever pulled
9 years old
54 releases · first in 2017
Visitor now receives the cookie jar through its constructor ( Illuminate\Contracts\Cookie\QueueingFactory ) and reads the existing visitor cookie from
Visitor now receives the cookie jar through its constructor (Illuminate\Contracts\Cookie\QueueingFactory) and reads the existing visitor cookie from the injected request, instead of going through the Cookie facade (breaking only for subclasses that override the constructor)views() helper now throws an InvalidArgumentException when given a class name that does not implement Contracts\Viewable, instead of a TypeError from deeper inside the packageViewableObserver now skips soft deletes and only destroys views on a force delete, so a restored model keeps its view count. If you relied on a soft delete purging views, call views($model)->destroy() yourselfCooldownManager built the session key to forget from an empty array_column() result, so it removed the whole namespace instead of the one expired entryVisitor::hasDoNotTrackHeader() always returning false; it looked the header up as HTTP_DNT, which is the $_SERVER key, while Laravel's header bag exposes it as DNT (the Visitor::DNT constant now holds 'DNT')orderByUniqueViews() and withViewsCount(unique: true) ordering and counting by total views instead of distinct visitors; Laravel drops the extra select added inside a withCount constraint, so the distinct count is now passed as the aggregate expressionOne column per quarter.
…instead of reading env('DB_CONNECTION') and the deprecated env('CACHE_DRIVER') (only affects newly published config)
See the upgrade guide for detailed migration instructions.
^8.5Views contract now declares the existing useVisitor() method (breaking only for classes that implement Contracts\Views directly)cooldown() and remember() parameters on the Views contract to be typed DateTimeInterface|int|nullscopeWithinPeriod() method on the View contract to declare a void return typePeriod::getStartDateTime()/getEndDateTime() to return ?CarbonInterfaceInvalidPeriod and ViewRecordException exceptions as final (breaking only for code that extends them)Viewable contract now uses @mixin \Illuminate\Database\Eloquent\Model instead of redeclaring the getKey() and getMorphClass() methodsView contract now uses @mixin \Illuminate\Database\Eloquent\Model and declares the existing scopeCollection() method (breaking only for classes that implement Contracts\View directly)create_views_table migration stub (typed properties and return types)visitor column in the create_views_table migration stub from text to string (VARCHAR(255)) so it can be indexed directly (only affects newly published migrations)models.view.connection and cache.store to null, so they now defer to the application's default database connection and cache store instead of reading env('DB_CONNECTION') and the deprecated env('CACHE_DRIVER') (only affects newly published config)Period as a final, immutable (readonly) value object; relative periods are now built with the new Support\PeriodInterval and Support\PeriodAnchor enums, and date parsing defers to Carbon::make() (the factory methods, getStartDateTime()/getEndDateTime(), and the cache-key format are unchanged)illuminate/* now requires ^13.0)nesbot/carbon now requires ^3.0)getStartDateTimeString(), getEndDateTimeString(), getStartDateTimestamp() and getEndDateTimestamp() getters from PeriodPeriod::PAST_* and Period::SUB_* constants and the sub(), subToday() and subNow() static helpersPeriod::getSubType(), getSubValue(), hasFixedDateTimes(), setStartDateTime(), setEndDateTime(), setFixedDateTimes(), setSubType() and setSubValue() methods (Period is now immutable)Fixed cooldown pruning when the session uses JSON serialization, where expires_at is restored as a string instead of a Carbon instance
expires_at is restored as a string instead of a Carbon instance (#326)Full Changelog: v7.1.0...v7.1.1
Changed Add support for Laravel 13
Implicitly marking parameter $collection as nullable is deprecated, the explicit nullable type must be used instead. by @mstnorris in #314
Full Changelog: v7.0.5...v7.0.6
refactor: fix deprecation warning. by @mikebronner in #312
Full Changelog: v7.0.4...v7.0.5
Support Laravel 12 by @bosunski in #302
Allow Carbon v3 by @cyrildewit in #299
Laravel 11 support by @janyksteenbeek in #295
Full Changelog: v7.0.1...v7.0.2
fixed deprecated variable in string by @Mahmoud217TR in #280
Full Changelog: v6.1.0...v7.0.1
Add support for Laravel 9 ( @atmonshi )
Revert breaking change of remember method in Views contract. The $lifetime variable has now a default value of null.
remember method in Views contract. The $lifetime variable has now a default value of null.Revert breaking change of remember method in Views class. The $lifetime variable has now a default value of null.
remember method in Views class. The $lifetime variable has now a default value of null.Added bool return typehint to record method in Views contract.
bool return typehint to record method in Views contract.void return typehint to destroy method in Views contract.ViewRecordException will be thrown when trying to record a view for a viewable type.ViewRecorded event will be fired when a new view is recorded.Views typehint to global views() function.bool return typehint to isCrawler method in CrawlerDetector contract.composer.json to ^7.4|^8.0.View instance has been moved into its own method protected function createView(): View.$viewable argument of the forViewable method in Views contract cannot be nullable anymore.orderByViews and orderByUniqueViews query scope in Viewable contract and InteractsWithViews trait.withViewsCount query scope in InteractsWithViews trait.Period class typehint to $period argument of period method in Views contract.$name argument nullable in Views contract.ip method in Visitor contract to ?string.DateTime typehint to DateTimeInterface in InvalidPeriod exception.lifetime_in_minutes option from config file.count method of Views class to count all views, including the collections (#241).Nothing published for this version
### Changed - Add support for Laravel 8
Use CyrildeWit\EloquentViewable\Contracts\Views to resolve Views instance from container.
CyrildeWit\EloquentViewable\Contracts\Views to resolve Views instance from container.Remove default value (null) for viewable in views() helper.
null) for viewable in views() helper.Removed the deprecated overrideIpAddress method from the Views class.
Views contract.Visitor contract.Visitor class which represents the current visitor.getViewableTypeSlug() to CacheKey::class.orderByViews query scope to Viewable trait.orderByUniqueViews query scope to Viewable trait.withViewsCount query scope to Viewable trait.CyrildeWit\EloquentViewable\Viewable trait has been renamed to CyrildeWit\EloquentViewable\InteractsWithViews.session.key to cooldown.key in configuration file.Views class constructor arguments. Added the Visitor as first argument and removed VisitorCookieRepository $visitorCookieRepository, CrawlerDetector $crawlerDetector and IpAddressResolver $ipAddressResolver.$this->crawlerDetector in Views with new Visitor class implementation.requestHasDoNotTrackHeader in Views with new Visitor class implementation.increments to bigIncrements in views table migration.^6.0|^7.0.getConnectionName(), getDatabaseName(), getModelSlug() and getKeySlug in CacheKey::class.ViewSessionHistory class to CooldownManager.CooldownManager class. The Illuminate\Contracts\Config\Repository has been added as first parameter and the cooldown key is now retrieved from this instance.Views class now implements the Views contract.Views class has been changed.Facades/Views to src/ and renamed it to ViewsFacade.views() helper now supports viewable types.nesbot/carbon ^1.22.overrideIpAddress method from the Views class.overrideVisitor method from the Views class.requestHasDoNotTrackHeader method from Views class.$viewableType argument from constructor of CacheKey::class.fromViewableType method from CacheKey::class.HeaderResolver contract and class.IpAddressResolver contract and class.uniqueVisitor() scope from View model.Enums\SortDirection class.OrderByViewsScope class.countByType method from the Views class.VisitorCookieRepository (logic is moved to the Visitor class).Nothing published for this version
Nothing published for this version
Nothing published for this version
Update required dependencies in composer.json to adhere to new Laravel 6 version scheme
### Changed - Add support for Laravel 6
Deprecated the overrideIpAddress method of the Views class. Please use the new useIpAddress(string $address) method instead.
SortDirection enum class that contains a DESCENDING and ASCENDING constantOrderByViewsScope class that can order a query by views based on some optionscollection($collection) query scope to View modelorderByViews and orderByUniqueViews query scopeCacheKey class with a new improved approach to making keys for the cachegetStartDateTimestamp and getEndDateTimestamp methods to the Period class for internal usestring $collection = null argument to push, createNamespaceKey and createViewableKey methods in ViewSessionHistoryoverrideIpAddress method of the Views class. Please use the new useIpAddress(string $address) method instead.overrideVisitor method of the Views class. Please use the new useVisitor(string $visitor) method instead.orderByViews and orderByUniqueViews query scope with the new OrderByViewsScope classstring type declaration from the getTable method in the View model class #165Support\Key class with its referencesUse String and Array classes instead of the helper functions
Fixed the ability to pass an integer to the delayInSession method without getting an error
delayInSession method without getting an errorThe method delayInSession isn't working properly
delayInSession isn't working properlyPublishing package migrations results in error
Added IpAddressResolver contract with implementation
Views class with facadeIpAddressResolver contract with implementationHeaderResolver contract with implementationVisitorCookieRepository classviewscollection column to views table schemawithinPeriod scope to View modeluniqueVisitor scope to View modelViewable contractviews() helperisBot method name to isCrawler in CrawlerDetector contract and updated the CrawlerDetectAdapter$detector property from protected to private5.7.* of illuminate/config to composer.jsonpublishable/config to config/create_views_table stub with real migration file and load it inside the service providerPeriod classPeriod class to the Key classViewTracker classViewableService classProcessView jobupdate_views_table migration file from resources/database/migrationsilluminate/bus as dependencyilluminate/queue as dependencyilluminate/routing as dependencyorderByViewsCount scope doesn't adhere to connection prefix
orderByViewsCount scope doesn't adhere to connection prefixData too long for column visitor
visitorProcessView job is always failing
View is saved before ProcessViews job is ran
Deprecated the CyrildeWit\Support\IpAddress class
CyrildeWit\Support\IpAddress classCyrildeWit\Viewtracker classscopeOrderByViewsCount method in the Viewable traitscopeOrderByUniqueViewsCount method in the Viewable traitAdd orderByUniqueViewsCount scope to Viewable trait
orderByUniqueViewsCount scope to Viewable traitAdd the ability to add a delay between views from the same session
This release accidentally contains no updates.
This release accidentally contains no updates.
This major version contains some serious breaking changes! See the upgrade guide for more information!
This major version contains some serious breaking changes! See the upgrade guide for more information!
visitor column to the create_views_table migration stubcyrildewit/laravel-page-view-counter to cyrildewit/eloquent-viewableHasPageViewCounter trait to ViewablePageViewCounterServiceProvider class to EloquentViewableServiceProviderCyrildeWit\PageViewCounter\xxx to 'CyrildeWit\EloquentViewable'addPageView method with addView in the Viewable traitgetPageViews<suffix> methods with getViews in the Viewable traitaddPageViewThatExpiresAt method from the Viewable traitNothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →