# Events and statistics

What the console shows about your game, where each number comes from, and what to track yourself.

The console's Statistics screen covers every site that lists your game, filterable by site, host, version
and locale, over a range of up to 400 days. Most of it comes from the SDK calls your game already makes.
`sdk.track()` adds what only your game knows.

## What you see

| Block          | What it counts                                                       | Where it comes from                                                                    |
| -------------- | -------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
| Active players | Per day, rolling 7 days, rolling 30 days; new and returning          | A play session: `gameplay.start()`                                                     |
| Sessions       | Count, mean and median length                                        | `gameplay.start()` to the end of the page or the last `stop()`                         |
| Retention      | D1, D7, D30 as cohorts by first-play week; blank under 10 players    | Sessions per player over time                                                          |
| Funnel         | Frame loaded, play started, save written, score sent, account linked | `ready()`, `gameplay.start()`, `save.set()`, `leaderboard.submit()`, the hub's sign-in |
| Events         | By name, with the number of players                                  | `sdk.track()`                                                                          |
| Splits         | Host, version, locale, device                                        | What the SDK sends with each session and event                                         |
| Boards         | Scores, best, median per board                                       | `leaderboard.submit()`                                                                 |
| Sites          | Sessions and players per site that lists the game                    | The site of each session                                                               |

Every table exports as CSV from the console. Nothing here is about money: filudi.com shows usage only.

## What to track

Track the decisions the funnel cannot see: a level cleared, a difficulty chosen, a tutorial skipped, a shop
opened, a run abandoned. Name events in `snake_case`, keep the set small, and keep the names across
versions; a renamed event starts a new line.

<CodePanel title="Events worth having">
  <Fragment slot="javascript">
    ```js
    sdk.track('level_complete', { level, moves, perfect: moves === par });
    sdk.track('level_fail', { level, reason: 'time' });
    sdk.track('tutorial_skip');
    sdk.track('difficulty_set', { difficulty: 'hard' });
    ```

  </Fragment>
  <Fragment slot="typescript">
    ```ts
    sdk.track('level_complete', { level, moves, perfect: moves === par });
    sdk.track('level_fail', { level, reason: 'time' });
    sdk.track('tutorial_skip');
    sdk.track('difficulty_set', { difficulty: 'hard' });
    ```

  </Fragment>
</CodePanel>

Limits: a name of at most 40 characters, 20 properties, each value at most 200 characters. The SDK sends 50
events or 5 s of them at a time, and the last batch leaves with the page. `frame_loaded` is reserved for
the hub.

## Version and device

Pass the release version to `init({ version })`. Every session and event carries it, and the version split
is how you compare a release with the previous one. The device is read by the API from the user agent at
session open, as `phone`, `tablet` or `desktop`; nothing else about the browser is kept.

## From portals

Sessions and events on CrazyGames, Poki and Playgama do not reach Filudi by default: no player token exists
there. `init({ events: 'always', eventsUrl })` sends events to the API anonymously, counted for the game's
site under the portal's host. Sessions, saves and scores on portals stay with the portal.

## When numbers appear

Today's events are read live; past days come from a daily rollup. Statistics answers are cached for 60 s.
A new version shows in the version filter after its first session.
