Lightweight analytics library for Telegram bots built with aiogram 3
Project description
Anystat
English | Русский
Lightweight, privacy-first analytics for Telegram bots built with aiogram 3.
Add two lines of code and see how people actually use your bot: /start sources and deep links, command usage, button clicks, blocks and unblocks — all in your Anystat dashboard.
anystat = Anystat(api_key="YOUR_API_KEY")
setup_anystat(dp, anystat)
Why Anystat
- Two-line integration. One middleware, zero changes to your handlers.
- Privacy by default. Message text is not collected unless you explicitly opt in. No user profile data is collected.
- Nothing hidden. Turn on
debug=Trueand the SDK logs every event it captures, every payload it sends, and everything it skips — verify it yourself. - Fire and forget. Events are batched, retried with backoff, and never block your handlers. If analytics fails, your bot keeps working.
- Fully typed. Ships with
py.typed— autocomplete and type checking out of the box.
Installation
pip install anystat
or with uv:
uv add anystat
Requires Python 3.12+ and aiogram 3.
Quickstart
import asyncio
from aiogram import Bot, Dispatcher
from anystat import Anystat, setup_anystat
async def main():
bot = Bot(token="YOUR_BOT_TOKEN")
dp = Dispatcher()
anystat = Anystat(api_key="YOUR_ANYSTAT_API_KEY") # 1
setup_anystat(dp, anystat) # 2
dp.shutdown.register(anystat.close) # flush pending events on shutdown
# ... register your handlers as usual ...
await dp.start_polling(bot)
asyncio.run(main())
That's it. Auto-tracking starts immediately — no changes to your handlers required.
You can also provide the API key via the ANYSTAT_API_KEY environment variable and create the client with just Anystat().
What gets tracked
| Event | Default | What it gives you |
|---|---|---|
/start command |
✅ on | New users and deep-link parameters (t.me/yourbot?start=campaign_x) — track where users come from |
| Other commands | ✅ on | Which commands people actually use |
| Callback queries | ✅ on | Inline button clicks |
| Bot blocked / unblocked | ✅ on | Churn: when users block or return to your bot |
| Text messages | ❌ off | Full message text — opt-in only, see below |
Every event includes the user ID, a timestamp, and how long your handler took to process the update (in ms).
What is NOT collected
- Message text — unless you explicitly set
track_messages=True. - User profile data (username, name, language) — profile collection is disabled in this version.
- Anything else. Don't take our word for it — run with
debug=Trueand watch every byte that leaves your bot.
Custom events
Track anything that matters to your bot with track():
from aiogram import types
from aiogram.filters import Command
@dp.message(Command("buy"))
async def buy_handler(message: types.Message):
# ... your logic ...
await anystat.track(
"purchase",
user_id=message.from_user.id,
amount=99,
currency="USD",
)
The first argument is the event name, the second is the user ID (or None for system events). Any extra keyword arguments become event properties — pass anything JSON-serializable.
Configuration
Pass options directly:
anystat = Anystat(
api_key="YOUR_API_KEY",
track_messages=True,
debug=True,
)
or group them in a config object:
from anystat import Anystat, AnystatConfig
config = AnystatConfig(track_messages=True, debug=True)
anystat = Anystat(api_key="YOUR_API_KEY", config=config)
Options passed directly to Anystat(...) override the config.
| Option | Default | Description |
|---|---|---|
debug |
False |
Log everything the SDK collects and sends (see below) |
track_start |
True |
Auto-track the /start command and its deep-link parameter |
track_command |
True |
Auto-track all other commands |
track_callback_query |
True |
Auto-track inline button clicks |
track_messages |
False |
Auto-track incoming text messages, including their text |
Debug mode: see exactly what leaves your bot
Trust, but verify. With debug=True the SDK logs every event it captures, every event it skips (and why), and the exact payload of every request:
[anystat] endpoint: https://api.anystat.me | api key: any_…7f2c
[anystat] auto-tracking: /start=on commands=on callbacks=on messages=off
[anystat] message text is NOT collected (track_messages=off)
[anystat] capture start_command via AnystatMiddleware:
{
"event_type": "start_command",
"user_id": 12345,
"received_at": 1767225600,
"duration": 12,
"message_id": 42,
"start_param": "campaign_x"
}
[anystat] skip message from user=12345 (track_messages=off, text not collected)
[anystat] → POST /v1/collect/events (2 events)
[anystat] ← 200 in 143 ms
Debug output goes through the standard logging module under the "anystat" logger. If you've already configured logging in your app, Anystat respects your handlers and formatting; otherwise it sets up a minimal [anystat] console handler for you.
Reliability
Analytics should never be the reason your bot breaks:
- Batching. Events are buffered in memory and sent in batches (up to 30 events or every 60 seconds), not one HTTP request per update.
- Retries. Network errors and retryable status codes (429, 5xx, …) are retried with exponential backoff and jitter.
- Non-blocking. Tracking runs after your handler finishes, so it never delays replies to users.
- Fail-safe. If the Anystat API is unreachable after retries, events are dropped with a warning in the logs — your bot keeps running.
Call await anystat.close() on shutdown (or register it as shown in the quickstart) to flush any buffered events before the process exits.
Requirements
- Python 3.12+
- aiogram >= 3.28
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file anystat-0.1.0.tar.gz.
File metadata
- Download URL: anystat-0.1.0.tar.gz
- Upload date:
- Size: 10.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
28d374490aa35d1cba656d026d1cb49cf15626ce818918191703a2b769dc75e8
|
|
| MD5 |
88640fae45f5904b59efe009519fd0b0
|
|
| BLAKE2b-256 |
bf1bf822b1fb0d7d4bc8216616a8ed02db9b7ac69ad18550e1442bb8bc1dc628
|
File details
Details for the file anystat-0.1.0-py3-none-any.whl.
File metadata
- Download URL: anystat-0.1.0-py3-none-any.whl
- Upload date:
- Size: 15.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1e0fa7ed8f32af3cf98df7791a58bb6a09cf2fcf542ac29be9232e3eee46d988
|
|
| MD5 |
ed40c059fcd1eec00e47827ae4a584fc
|
|
| BLAKE2b-256 |
506c98c7e1da0f7953cf7ab5fe9084ae1f6bff4117942e8aa70e4b26a9ab2578
|