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 Statistics Laravel Package

rinvex/laravel-statistics

Rinvex Laravel Statistics adds lightweight, model-based analytics to Laravel apps. Attach a trait to any Eloquent model to record and query daily, monthly, and yearly hits, views, and custom metrics via polymorphic relations, with caching and configurable tracking built in.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Install and publish the package's config and migrations, then migrate:
composer require rinvex/laravel-statistics
php artisan vendor:publish --provider="Rinvex\Statistics\Providers\StatisticsServiceProvider"
php artisan migrate
  • Look first at these files, in this order:

    1. config/statistics.php — tracking switches, storage options, and any command/middleware configuration.
    2. The published migration — it defines the statistics table columns and indexes; edit it before migrating in production if you need UUID users, tenant IDs, or fewer stored fields.
    3. Rinvex\Statistics\Http\Middleware\TrackStatistics (older versions) or the Statistic polymorphic model (newer versions) — these are the two integration surfaces.
    4. Rinvex\Statistics\Models\Statistic — the query surface you will use for every report.
  • Wire tracking into the app. For visit-style tracking, register the middleware on the routes you care about:

Route::middleware(\Rinvex\Statistics\Http\Middleware\TrackStatistics::class)
    ->group(function () {
        Route::get('/', HomeController::class);
        Route::get('/articles/{article}', [ArticleController::class, 'show']);
    });

For polymorphic-style tracking, attach a statistic directly to any model:

use Rinvex\Statistics\Models\Statistic;

$article->statistics()->create([
    'type'  => 'view',
    'value' => 1,
]);
  • First use case: load any tracked page, then confirm a row exists:
php artisan tinker
>>> Rinvex\Statistics\Models\Statistic::latest()->first();

If you see a row, the wiring is correct. From there, build a "visits per day" or "top pages this week" query against the model.

This package is archived. Treat the installed version as frozen, test it against your Laravel/PHP version, and plan to fork or vendor it if you depend on it.

Implementation Patterns

  • Track selectively, not globally. Apply the tracking middleware only to public-facing route groups. Avoid polluting analytics with admin panels, health checks, webhooks, and API routes:
Route::middleware(\Rinvex\Statistics\Http\Middleware\TrackStatistics::class)
    ->group(base_path('routes/public.php'));
  • Keep middleware order deliberate. Place TrackStatistics inside the web group after StartSession and auth middleware, so session_id, user_id, and referrer are populated. If it runs earlier, user/session attribution is empty.

  • Use the polymorphic API for feature-level metrics. Beyond visits, the model attaches to anything via morphMany — record likes, shares, downloads, or custom events. Prefer one row per event with a value column rather than repeatedly updating a counter, so you keep history.

$post->statistics()->create(['type' => 'like', 'value' => 1]);

// Aggregated read
$post->statistics()->where('type', 'like')->sum('value');
  • Build reporting on aggregate queries, not raw dumps. Typical day-to-day queries:
use Rinvex\Statistics\Models\Statistic;
use Illuminate\Support\Facades\DB;

// Daily visits
Statistic::query()
    ->whereBetween('created_at', [$from, $to])
    ->selectRaw('DATE(created_at) as day, COUNT(*) as visits')
    ->groupBy('day')
    ->orderBy('day')
    ->get();

// Top pages, last 30 days
Statistic::query()
    ->where('created_at', '>=', now()->subDays(30))
    ->select('request_path', DB::raw('COUNT(*) as visits'))
    ->groupBy('request_path')
    ->orderByDesc('visits')
    ->limit(20)
    ->get();

Cache these results (5–60 minutes) if dashboards are frequently viewed.

  • Schedule the package's crunch/crush command. The package is designed around a cron aggregation/cleanup step. Discover the exact name after install:
php artisan list | grep statistics

Then schedule it:

$schedule->command('statistics:crush')
    ->daily()
    ->withoutOverlapping()
    ->onOneServer();

Verify in code/config whether the command aggregates, prunes, or both before enabling in production.

  • Separate raw tracking from business reporting. Keep the statistics table as an append-only event log; write derived daily/weekly aggregates into your own summary table. Fast dashboards, easy retention pruning, and reports survive schema changes.

  • Add retention and partitioning early. A row-per-request table grows fast. Choose a window (e.g. 30–90 days for raw), prune on schedule, and archive aggregates if you need long-term trends.

  • Handle load deliberately. The package does a synchronous insert per tracked request. Under load, either dispatch tracking to a queue, sample (1 in N), write to a separate connection, or restrict tracking to important routes.

  • Handle privacy explicitly. Strip or avoid request bodies, headers, cookies, and raw IPs. Add a consent check if you operate under GDPR/CCPA, and document what is stored and for how long.

  • Exclude bots from product reporting. Use the is_bot flag consistently; otherwise crawler traffic dominates page-view metrics.

  • Test without tracking noise. In feature tests:

$this->withoutMiddleware(\Rinvex\Statistics\Http\Middleware\TrackStatistics::class);

For integration tests, use RefreshDatabase and assert a statistics row exists after a request.

Gotchas and Tips

  • Archived dependency risk. The package is unmaintained. Composer may resolve an old version; future Laravel upgrades can break it. Pin the version, test upgrades in isolation, and be prepared to fork or inline the code.

  • Middleware placement is the most common failure. If user_id, session_id, or referrer are empty, the middleware is almost certainly running before session/auth middleware or outside the web group.

  • Schema assumptions break migrations. The default migration often assumes an auto-incrementing users.id. If you use UUIDs, ULIDs, or a different auth table, edit the published migration before running it — not after.

  • Sensitive data may be stored by default. Request headers, bodies, cookies, and referrers can contain tokens or personal data. Review the published migration/config, drop columns you do not need, and sanitize before deploy.

  • "One query per request" is still a write per request. Cheap individually, expensive at scale. Monitor table size and insert latency. Add indexes on created_at, user_id, request_path, and any polymorphic keys (statisticable_type, statisticable_id) used in reports.

  • Bot detection is heuristic. Expect false positives and negatives. Do not use bot flags for security decisions — only for analytics hygiene.

  • Config caching catches people out. After editing config/statistics.php or related .env values:

php artisan config:clear
php artisan config:cache
  • Understand the crunch/crush command before scheduling it. If it prunes raw data, you lose historical detail permanently. Back up or export first and confirm the retention window in code/config.

  • Timezone and date grouping. whereDate() and DATE(created_at) follow the effective DB/app timezone. Keep storage, reporting, and schedules consistent — especially around daily boundaries and DST.

  • Internal traffic pollutes metrics. Exclude /up, /health, /horizon, asset routes, and webhook endpoints. A noisy top-pages list is usually your own infrastructure.

  • Referrer and language are best-effort. Treat them as directional, not reliable attribution. Validate lengths before storing custom values or you will hit truncation.

  • Extension is limited. For custom fields (tenant ID, experiment bucket, UTM parameters), the safest pattern is to publish/modify the migration and either extend the model or write your own lightweight tracking middleware/service. Do not fight package internals for fields it does not know about.

  • Route caching and Octane. The middleware is generally route-cache and Octane compatible, but long-running workers can retain stale config. Clear caches on deploy and restart Octane workers after config changes.

  • Consider alternatives for new projects. For new work, evaluate a small custom middleware + event table, Spatie's analytics package, or a hosted service. This package is best treated as a compact self-hosted visit log — a validated pattern to borrow — rather than a long-term dependency or a full analytics platform.

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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core