Self-hosted, privacy-first analytics controlled entirely through a Telegram bot. No dashboard. No third parties. Just Telegram.
- Docker & Docker Compose v2
- A Telegram bot token from @BotFather
- Your Telegram chat ID (message @userinfobot to find it)
git clone https://github.com/tgram-analytics/server.git
cd server
cp .env.example .env
# Edit .env and fill in TELEGRAM_BOT_TOKEN, ADMIN_CHAT_ID, and SECRET_KEYGenerate a SECRET_KEY:
python -c "import secrets; print(secrets.token_hex(32))"docker compose upThe server starts on http://localhost:8000.
Verify it's running:
curl http://localhost:8000/health
# {"status":"ok"}Open Telegram and message your bot:
/add myapp.com
The bot replies with your API key (proj_xxxx) and a ready-to-use JS snippet.
curl -X POST https://your-server.com/api/v1/track \
-H "Content-Type: application/json" \
-d '{
"api_key": "proj_xxxxxxxxxxxx",
"event": "purchase",
"session_id": "uuid-here",
"properties": {"amount": 49, "plan": "pro"}
}'<script src="https://your-server.com/sdk/tga.min.js"></script>
<script>
TGA.init('proj_xxxxxxxxxxxx', { serverUrl: 'https://your-server.com' });
TGA.track('purchase', { amount: 49 });
</script>await TgAnalytics.init(
apiKey: 'proj_xxxxxxxxxxxx',
serverUrl: 'https://your-server.com',
);
await TgAnalytics.track('purchase', properties: {'amount': 49});| Command | Description |
|---|---|
/start |
Greet the bot and see available commands |
/add <name> |
Create a new project and get its API key |
/projects |
List all projects |
/report <event> |
Get a chart for an event (with period/granularity controls) |
/settings |
Configure retention and domain allowlist |
/help |
Show this command reference |
python -m venv .venv
source .venv/bin/activate
make install
cp .env.example .env # edit valuesmake dev-db # start postgres + quickchart in Docker
make migrate # apply migrations
uvicorn app.main:app --reloadmake test # run all tests
make test-cov # with coverage reportmake lint # ruff linter
make typecheck # mypy
make check # both# Create a new migration
make migration MSG="add users table"
# Apply migrations
make migrate
# Roll back one step
make downgradeapp/
├── api/ REST endpoints (track, pageview, projects)
├── bot/ Telegram bot handlers and conversation state
├── core/ Config, database engine, security utilities
├── models/ SQLAlchemy ORM models
├── schemas/ Pydantic request/response schemas
└── services/ Analytics, charts, scheduler, alerts
See PROJECT.md for full architecture documentation.
cp .env.example .env
# Fill in all values, especially WEBHOOK_BASE_URL=https://your-domain.com
docker compose up -dPoint your reverse proxy (Nginx/Caddy) at port 8000.
Add the environment variables from .env.example in the Railway dashboard.
Contributions are welcome. Please open an issue before submitting a pull request for anything beyond a typo or small bug fix, so we can discuss the approach first.
- Fork the repository
- Create a feature branch:
git checkout -b feat/my-feature - Write tests alongside your code
- Ensure
make checkandmake testpass - Open a pull request
Please follow the existing code style (ruff-enforced) and keep PRs focused.
This project is an independent open-source project, not affiliated with or endorsed by Telegram Messenger LLP or its parent company in any way. "Telegram" is a trademark of Telegram Messenger LLP.
MIT — see the file for details.