PHPackages                             elegantly/laravel-kpi - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. elegantly/laravel-kpi

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

elegantly/laravel-kpi
=====================

Advanced KPI for your Laravel application

v1.2.1(1y ago)173.7k↓53.5%2[3 PRs](https://github.com/ElegantEngineeringTech/laravel-kpi/pulls)1MITPHPPHP ^8.2CI passing

Since Sep 3Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/ElegantEngineeringTech/laravel-kpi)[ Packagist](https://packagist.org/packages/elegantly/laravel-kpi)[ Docs](https://github.com/elegantengineeringtech/laravel-kpi)[ GitHub Sponsors](https://github.com/ElegantEngineeringTech)[ RSS](/packages/elegantly-laravel-kpi/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (14)Versions (25)Used By (1)

Store, Analyze, and Retrieve KPIs Over Time in Your Laravel App
===============================================================

[](#store-analyze-and-retrieve-kpis-over-time-in-your-laravel-app)

[![Latest Version on Packagist](https://camo.githubusercontent.com/a92a90114f40f719c89c251c6390543b0997c73ac1c64c116f8049569bf39b19/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f656c6567616e746c792f6c61726176656c2d6b70692e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/elegantly/laravel-kpi)[![GitHub Tests Action Status](https://camo.githubusercontent.com/27f1e132ee67385aebdee09899ccbb5c99f911c8e0a02b7eda0b9393b409da4e/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f456c6567616e74456e67696e656572696e67546563682f6c61726176656c2d6b70692f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/ElegantEngineeringTech/laravel-kpi/actions?query=workflow%3Arun-tests+branch%3Amain)[![GitHub Code Style Action Status](https://camo.githubusercontent.com/fb727df46a61e6f6ce79a6a3433487ae21a94aac3525fb188d666398c5b9ec5d/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f456c6567616e74456e67696e656572696e67546563682f6c61726176656c2d6b70692f6669782d7068702d636f64652d7374796c652d6973737565732e796d6c3f6272616e63683d6d61696e266c6162656c3d636f64652532307374796c65267374796c653d666c61742d737175617265)](https://github.com/ElegantEngineeringTech/laravel-kpi/actions?query=workflow%3A%22Fix+PHP+code+style+issues%22+branch%3Amain)[![Total Downloads](https://camo.githubusercontent.com/e04b270b7b687a7da315ffe1453e1ca9dd61aa5af393aedca982c3758b8935be/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f656c6567616e746c792f6c61726176656c2d6b70692e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/elegantly/laravel-kpi)

[![laravel-seo](https://repository-images.githubusercontent.com/836316961/3690c066-4681-48c9-8a37-be709899bd94)](https://repository-images.githubusercontent.com/836316961/3690c066-4681-48c9-8a37-be709899bd94)

This package provides an easy way to store KPIs from your application in your database and retrieve them in various formats. It's especially useful for tracking data related to your models, such as:

- Number of users
- Number of subscribed users
- Total revenue
- And more...

It's a perfect tool for building dashboards and displaying stats and charts.

Filament Plugin
---------------

[](#filament-plugin)

Display your KPIs in a beatiful way with 1 line using our filament plugin: [`elegantly/filament-kpi`](https://github.com/ElegantEngineeringTech/filament-kpi)

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

[](#installation)

Install the package via Composer:

```
composer require elegantly/laravel-kpi
```

Publish and run the migrations with:

```
php artisan vendor:publish --tag="kpi-migrations"
php artisan migrate
```

Publish the configuration file with:

```
php artisan vendor:publish --tag="kpi-config"
```

Here is the content of the published config file:

```
return [

    /*
    |--------------------------------------------------------------------------
    | Discover Definitions
    |--------------------------------------------------------------------------
    |
    | If 'enabled' is set to true, your KPI definitions will be automatically
    | discovered when taking snapshots.
    | Set the 'path' to specify the directory where your KPI definitions are stored.
    | Definitions will be discovered from this path and its subdirectories.
    |
    */
    'discover' => [
        'enabled' => true,
        /**
         * This path will be used with the `app_path` helper, like `app_path('Kpis')`.
         */
        'path' => 'Kpis',
    ],

    /*
    |--------------------------------------------------------------------------
    | Registered Definitions
    |--------------------------------------------------------------------------
    |
    | You can manually register your KPI definitions if you are not using
    | "discover" or if you want to add additional definitions located elsewhere.
    |
    */
    'definitions' => [],
];
```

Concepts
--------

[](#concepts)

This package is not a query builder. Instead, it is based on a `kpis` table where all KPIs are stored. This allows historical data (e.g., the number of users a year ago) to remain intact, even if models are permanently deleted.

Retrieving KPIs is also way more efficient when calculating complex values, such as "users who made a purchase last week."

A KPI can be simple or complex. Examples include:

- Number of registered users
- Monthly active users
- Total revenue invoiced to customers
- Number of recurring customers
- Average Order Value
- ...

KPIs can be either "absolute" or "relative":

- An **absolute KPI** represents a current state, such as the total number of users.
- A **relative KPI** represents a change, such as the number of new users each day.

Depending on the context, either an absolute or relative KPI may be more relevant. In most cases, relative KPIs can be derived from absolute ones, and vice versa. Therefore, it's often recommended to store KPIs as "absolute" and compute relative values when needed.

Usage
-----

[](#usage)

A KPI consists of two key components:

- A **definition**
- Its **values**

The **definition** is a class extending `KpiDefinition`, where you configure the KPI.

Each KPI definition must have a unique `name`, such as `users:count`.

The **values** are stored in the `kpis` table and represented by the `Kpi` model.

A KPI value may contain:

- A value (float, string, Money, JSON)
- A description (optional)
- Tags (optional)
- Metadata (optional)
- A timestamp

### 1. Defining a KPI

[](#1-defining-a-kpi)

Each KPI is represented by a single `KpiDefinition` class. The package offers predefined classes for each data type:

- `KpiFloatDefinition`
- `KpiStringDefinition`
- `KpiMoneyDefinition`
- `KpiJsonDefinition`

You can also extend `KpiDefinition` if you need custom behavior.

Example:

```
namespace App\Kpis\Users;

use App\Models\User;
use Elegantly\Kpi\Enums\KpiInterval;
use Elegantly\Kpi\KpiFloatDefinition;

class UsersCountKpi extends KpiFloatDefinition
{
    public static function getName(): string
    {
        return 'users:count';
    }

    /**
     * This KPI is intended to be snapshotted every day.
     */
    public static function getSnapshotInterval(): KpiInterval
    {
        return KpiInterval::Day;
    }

    public function getValue(): float
    {
        return (float) User::query()
            ->when($this->date, fn ($query) => $query->where('created_at', 'command(SnapshotKpisCommand::class, [
    'interval' => KpiInterval::Hour,
])->everyHour();

$schedule->command(SnapshotKpisCommand::class, [
    'interval' => KpiInterval::Day,
])->daily();
```

#### Manual Snapshot

[](#manual-snapshot)

You can manually snapshot a KPI using the `snapshot` method:

```
use App\Kpis\Users\UsersCountKpi;

UsersCountKpi::snapshot(
    date: now()
);
```

### 3. Seeding KPIs

[](#3-seeding-kpis)

#### Seeding with the Command

[](#seeding-with-the-command)

When adding KPIs to an existing project, you may want to seed past data. If your `KpiDefinition` class supports the `date` property, you can seed KPIs using the following command:

```
php artisan kpis:seed "one year ago" "now"
```

#### Manual Seeding

[](#manual-seeding)

You can also seed KPIs manually using the `seed` method:

```
use App\Kpis\Users\UsersCountKpi;

UsersCountKpi::seed(
    from: now()->subYear(),
    to: now(),
    interval: KpiInterval::Day
);
```

### 4. Querying KPIs

[](#4-querying-kpis)

To visualize KPIs in charts or dashboards, the `KpiDefinition` class provides several helper methods:

```
use App\Kpis\Users\UsersCountKpi;

/**
 * Retrieve a collection of KPIs for a given period, keyed by date.
 */
UsersCountKpi::getPeriod(
    start: now()->subDays(6),
    end: now(),
    interval: KpiInterval::Day
);

/**
 * Retrieve a collection of relative KPIs (i.e., the difference between consecutive snapshots).
 */
UsersCountKpi::getDiffPeriod(
    start: now()->subDays(6),
    end: now(),
    interval: KpiInterval::Day
);
```

### 5. Aggregating KPIs

[](#5-aggregating-kpis)

You can easily aggregate KPIs using the following methods:

```
/**
 * Retrieve the KPI with the maximum value for each month.
 */
UsersCountKpi::max(
    start: now()->subMonths(6),
    end: now(),
    interval: KpiInterval::Month
);

UsersCountKpi::min(...);
UsersCountKpi::avg(...);
UsersCountKpi::sum(...);
UsersCountKpi::count(...);
```

### Storing Kpis in a separate database

[](#storing-kpis-in-a-separate-database)

To reduce the write load this package creates on your primary database, you can store your KPIs in a different database.

Follow these steps to set it up:

#### 1. Create your own Kpi class

[](#1-create-your-own-kpi-class)

In your application, create a custom model by extending the default one.

Ensure you define the connection property. You may also define the table property if necessary.

```
namespace \App\Models;

class Kpi extends \Eleganlty\Kpi\Models\Kpi
{
    /**
     * The database connection that should be used by the model.
     *
     * @var string
     */
    protected $connection = 'mysql';

}
```

#### 2. Publish and edit the config

[](#2-publish-and-edit-the-config)

In your `kpi` configuration file, specify your custom class as the KPI model:

```
return [
    //...

    'model' => \App\Models\Kpi::class

    //...
]
```

#### 3. Publish and edit the migration

[](#3-publish-and-edit-the-migration)

Ensure you specify the correct connection and table in the migration file.

It should look like this:

```
return new class extends Migration
{
    public function up()
    {
        Schema::connection('mysql')->create('kpis', function (Blueprint $table){
            // ...
        });
    }

    public function down(): void
    {
        Schema::connection('mysql')->dropIfExists('kpis');
    }

}
```

Testing
-------

[](#testing)

Run the tests with:

```
composer test
```

Changelog
---------

[](#changelog)

For recent changes, see the [CHANGELOG](CHANGELOG.md).

Contributing
------------

[](#contributing)

For contribution guidelines, see [CONTRIBUTING](CONTRIBUTING.md).

Security Vulnerabilities
------------------------

[](#security-vulnerabilities)

For details on reporting security vulnerabilities, review [our security policy](../../security/policy).

Credits
-------

[](#credits)

- [Quentin Gabriele](https://github.com/QuentinGab)
- [All Contributors](../../contributors)

License
-------

[](#license)

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

###  Health Score

48

—

FairBetter than 94% of packages

Maintenance69

Regular maintenance activity

Popularity31

Limited adoption so far

Community16

Small or concentrated contributor base

Maturity62

Established project with proven stability

 Bus Factor1

Top contributor holds 74.4% 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 ~9 days

Recently: every ~44 days

Total

20

Last Release

439d ago

### Community

Maintainers

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

---

Top Contributors

[![QuentinGab](https://avatars.githubusercontent.com/u/40128136?v=4)](https://github.com/QuentinGab "QuentinGab (64 commits)")[![antoniofrignani](https://avatars.githubusercontent.com/u/802713?v=4)](https://github.com/antoniofrignani "antoniofrignani (10 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (7 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (5 commits)")

---

Tags

kpilaravellaravel-packagemetricslaravelMetricsElegantEngineeringTechlaravel-kpikpi

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/elegantly-laravel-kpi/health.svg)

```
[![Health](https://phpackages.com/badges/elegantly-laravel-kpi/health.svg)](https://phpackages.com/packages/elegantly-laravel-kpi)
```

###  Alternatives

[spatie/laravel-data

Create unified resources and data transfer objects

1.7k28.9M627](/packages/spatie-laravel-data)[spatie/laravel-livewire-wizard

Build wizards using Livewire

4061.0M4](/packages/spatie-laravel-livewire-wizard)[hirethunk/verbs

An event sourcing package that feels nice.

513162.9k6](/packages/hirethunk-verbs)[worksome/exchange

Check Exchange Rates for any currency in Laravel.

123544.7k](/packages/worksome-exchange)[ralphjsmit/livewire-urls

Get the previous and current url in Livewire.

82270.3k4](/packages/ralphjsmit-livewire-urls)[hydrat/filament-table-layout-toggle

Filament plugin adding a toggle button to tables, allowing user to switch between Grid and Table layouts.

6292.3k1](/packages/hydrat-filament-table-layout-toggle)

PHPackages © 2026

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