# Panel Analytics Hooks

https://dev.wisecp.com/es/admin-analytics-hooks

The six hooks over report figures, date ranges, charts and live counters.

## Overview

Every number on the report pages passes through these hooks: summary figures, time series, distributions and finance totals. Beside them sits the read-only event of the live counters.

One rule runs through all of them: **keep the shape**. The chart library and the queries that follow expect particular keys; a missing or mismatched structure quietly yields an empty report.

## Reference

### Following a live metric poll

actionadmin.analytics.realtime_polled

`admin/analytics` read only

Runs when the live counters on the board refresh. It repeats **at regular intervals** while the page is open.

Parameters 1

$statsarrayThe live metrics: how many are online, visitors in the last five minutes, and map markers. A copy is passed: **changing it has no effect**. It is deliberately an event, not a filter.

Return 1

voidThe return is ignored; the data cannot be changed.

Listener PHP

```php
Hook::add('action:admin.analytics.realtime_polled', 10, function ($stats) {
    // A copy is passed: changing it has no effect.
    Acme::pushMetric('online', (int) ($stats['online_count'] ?? 0));
});
```

### Changing the report date range

filteradmin.analytics.date_range

`admin/analytics` keys must survive

Runs after the date range picked by the user is resolved. Every report query uses that range.

Parameters 2

$resultarrayby linkThe resolved range: start, end, the previous period’s start and end, and the day count. ? **Every key must survive**: a missing one breaks the queries that follow and the report comes out empty.

$rangestringThe raw range text from the user.

Return 1

voidThe return is ignored; you write over the data.

Listener PHP

```php
Hook::add('filter:admin.analytics.date_range', 10, function (&$result, $range) {
    // Every key must stay: a missing one empties the report.
    $result['start'] = Acme::fiscalStart($result['start']);
});
```

### Changing the summary figures

filteradmin.analytics.kpis

`admin/analytics` shape follows the section

Runs once the summary figures at the top of a report page are worked out.

Parameters 3

$kpisarrayby linkThe values worked out. ? **Its shape follows the section**: the keys in the client report are not the keys in the service report. Check the section before reaching for a key.

$sectionstringThe report section: clients, services or support.

$rangearrayThe active date range.

Return 1

voidThe return is ignored; you write over the data.

Listener PHP

```php
Hook::add('filter:admin.analytics.kpis', 10, function (&$kpis, $section, $range) {
    // The shape follows the section: check it first.
    if ($section !== 'clients') return;

    $kpis['acme_churn'] = Acme::churnRate($range);
});
```

### Changing the time series

filteradmin.analytics.trend_series

`admin/analytics` equal lengths required

Runs once the chart data is worked out.

Parameters 3

$trendarrayby linkLabels and one or more value series. ? **The labels and the series must be the same length**; the chart draws its axes from that. Keep the existing series keys and add a new series under its own key.

$reportstringThe report key: income, expense, profit and loss, clients, services or support.

$rangearrayThe active date range.

Return 1

voidThe return is ignored; you write over the data.

Listener PHP

```php
Hook::add('filter:admin.analytics.trend_series', 10, function (&$trend, $report, $range) {
    // Labels and series must be the same length.
    if ($report !== 'income') return;

    $trend['acme_forecast'] = Acme::forecast(count($trend['labels'] ?? []));
});
```

### Changing the distribution data

filteradmin.analytics.distribution

`admin/analytics` fixed item shape

Runs once the distribution chart data is worked out.

Parameters 4

$dataarrayby linkThe distribution items. Each item must carry a **label and a value**; the chart library expects that shape and any other quietly yields an empty chart.

$entitystringWhat is distributed: clients, services or tickets.

$typestringThe kind: status, country, language, product, period, priority, department, staff or response time.

$rangearrayThe active date range.

Return 1

voidThe return is ignored; you write over the data.

Listener PHP

```php
Hook::add('filter:admin.analytics.distribution', 10,
    function (&$data, $entity, $type, $range) {
        // Every item must carry a label and a value.
        if ($entity === 'client' && $type === 'country')
            $data = Acme::mergeSmallCountries($data);
    });
```

### Changing the finance summary

filteradmin.analytics.invoice_report_totals

`admin/analytics` currency filtered

Runs once the summary totals of a finance report are worked out.

Parameters 4

$totalsarrayby linkThe summary totals: count, amount, day count, daily average and currency.

$reportstringWhich report: income, expense, profit and loss, tax, cancelled, refunded or payment method.

$rangearrayThe active date range.

$currency_idintThe currency filtered on; a **zero** means the base currency.

Return 1

voidThe return is ignored; you write over the data.

Listener PHP

```php
Hook::add('filter:admin.analytics.invoice_report_totals', 10,
    function (&$totals, $report, $range, $currency_id) {
        // A zero currency means the base currency.
        if ($report === 'income') $totals['acme_target'] = Acme::monthlyTarget($currency_id);
    });
```

## Pitfalls

> **Dropping a date-range key empties the report**
> 
> Every key in the range array is read by the queries that follow. Removing one or renaming it breaks the figure and chart queries; what appears on screen is not an error but an **empty report**, which makes it hard to spot.

> **Labels and series must be the same length**
> 
> If the label count and the value count part ways in a time series the chart axes slip. Build a new series to the length of the existing labels, and keep the series keys already there.

## Related Articles

- [Management Panel Hooks](https://dev.wisecp.com/en/hooks-in-the-management-panel)
- [Customer Account Hooks](https://dev.wisecp.com/en/customer-account-hooks)
- [How Hooks Work](https://dev.wisecp.com/en/how-hooks-work)
