Vitals — key metrics
The Vitals page collects the key growth and retention metrics for a single bot: active users, new users, retention and churn.
On the dashboard you pick the time range yourself. Vitals works differently: every activity metric is computed over complete calendar periods. That keeps the numbers comparable with your reporting, and stops them drifting over the course of a day.
Who counts as an active user
An active user is a person who did something themselves: sent a message, tapped a button, voted in a poll, left a reaction.
What is not counted:
- Messages the bot sent. A broadcast does not make its recipient active — otherwise messaging your whole list would make "active users" equal your subscriber count. For the same reason a broadcast does not create new users either.
- The bot itself, and technical rows with no identifiable author.
- A chat instead of a person. In a group, every member who posted is counted, not the group.
The Events metric counts events, and a message the bot sends is also an event. So a broadcast
can raise your event count while leaving active users unchanged. If you want the reach of a
broadcast, build a widget filtered on $tg.direction = outbound.
Complete calendar periods
DAU, WAU and MAU count the last complete calendar period — not the last 24 hours, 7 days or 30 days.
| Metric | Period | Example on 28 July 2026 |
|---|---|---|
| DAU | last complete day | July 27, 2026 |
| WAU | last complete week (Mon – Sun) | July 20 – 26, 2026 |
| MAU | last complete calendar month | June 2026 |
The period currently in progress is excluded.
Why not "the last 30 days"
A rolling window that ends at now splices two partial days together: yesterday's tail plus today's head. The count is real, but it is not the count of any period you can name — so it cannot be reconciled against a report, an invoice, or someone else's spreadsheet. It also changes every time the page reloads.
A completed period behaves differently: once the period closes, its value is fixed for good. This is how MAU-based billing works (Auth0, Firebase, Segment), and how MAU is published in financial reporting.
The caption under each number states the period outright — for example, June 2026 (UTC) · vs the month before. A metric whose period is not named cannot be audited.
Time zone and start of week
- All period boundaries are computed in UTC.
- Weeks start on Monday (ISO 8601).
This is not an arbitrary choice. Cohorts in the Retention widget are grouped server-side by UTC and by Monday-start weeks. If Vitals used the viewer's local calendar, MAU and the retention cohorts on the same page would disagree by construction.
If you are in UTC+3, the DAU "day" runs 03:00 to 03:00 in your local time, not 00:00 to 00:00. A per-project time zone setting is planned; for now a single UTC calendar guarantees the metrics agree with each other.
Comparison with the previous period
The badges on each card show the change against the previous period of the same calendar kind.
| Metric | Compared with |
|---|---|
| DAU | the day before |
| WAU | the week before |
| MAU | the previous calendar month |
The two periods are contiguous — no gap, no overlap — so no user lands in both at once.
February (28 days) is compared with January (31 days). That is a calendar-to-calendar comparison, not a fixed 30-day shift, so part of any MAU change between such months is explained by their length alone. There is deliberately no normalisation: "MAU over 30.4 days" cannot be reconciled against anything.
Reporting lag
A completed period carries an unavoidable cost — lag:
- DAU is at most one day behind.
- WAU up to 7 days: on a Sunday you are still seeing the week before last.
- MAU up to 31 days: on 31 July, MAU still reports June.
This is a property of the metric, not a fault. If you need activity for the period currently in progress, build a KPI widget on the dashboard with the Users metric and the range you want — see Metrics.
New users
The New Users · Day / Week / Month cards count unique users whose first-ever action falls in the matching completed period.
This used to read "who sent /start", which described an earlier implementation and was inaccurate: a user was counted as new again on every repeat /start, and anyone who never sent one was missed entirely. The metric now looks at the first action of any kind.
The periods match DAU, WAU and MAU deliberately: two cards side by side carrying the same period caption must mean the same thing.
Retention and Churn
Retention 7D is the share of users who came back at least once within 7 days of joining. Not "on day 7 exactly": someone who returned on day 3 and never again is counted. 1D and 30D work the same way.
Churn 30D = 1 − Retention 30D: the estimated share who did not come back at all within 30 days.
Both are averaged over cohorts from a rolling 90-day window, weighted by cohort size. That is a cohort observation window rather than a reporting period, so it is not tied to the calendar.
A cohort formed yesterday cannot have a 30-day figure — 30 days have not passed. Those cohorts are left out of the average: their zero means "the measurement is unfinished", not "nobody came back". If no cohort is yet old enough, the card shows n/a rather than an understated number.
In the Retention widget each column is one period: Day 7 means "came back on day 7". On Vitals the figures are cumulative — "came back within N days". Retention 7D on Vitals is therefore always at least the Day 7 cell in that table, and that is not a data discrepancy.
What's next?
- Metrics — how Users, Events and Events per User work
- Widget types — Retention, Cohort and the rest
- Dashboard overview — time range, granularity and filters