analytics / README.md
nanye's picture
track location and timezone
a10ad9b
|
Raw History Blame Contribute Delete
5 kB
---
title: HF Space Analytics
emoji: πŸ“Š
colorFrom: yellow
colorTo: indigo
sdk: docker
pinned: false
license: mit
---
# HF Space Analytics β€” Gradio Edition
A small Gradio Space that tracks page views across your other Hugging Face Spaces. Gradio provides the dashboard, while an embedded FastAPI application provides the tracking endpoints.
## Features
- Gradio dashboard at `/`
- `POST /track` β€” record a page-view event
- `GET /stats` β€” aggregated visit counts
- `GET /events` β€” recent raw events
- `GET /tracker.js` β€” reusable browser tracker
- `GET /health` β€” health and storage check
- Daily JSONL storage in an attached Hugging Face Storage Bucket
## 1. Create the analytics Space
1. Create a new Hugging Face Space.
2. Select **Gradio** as the SDK.
3. Select **ZeroGPU** hardware. Dashboard refreshes use a one-second ZeroGPU allocation;
tracking and API requests remain CPU-only.
4. Upload every file in this project, or push the repository with Git.
5. In the Space settings, attach a Hugging Face Storage Bucket as a read-write volume mounted at `/data`.
6. Add the optional variables and secrets below.
| Name | Type | Purpose |
|---|---|---|
| `TRACKING_KEY` | Secret | Required in tracking requests when set |
| `ADMIN_KEY` | Secret | Protects `/stats`, `/events`, and the dashboard when set |
| `ALLOWED_ORIGINS` | Variable | Comma-separated CORS origins; default `*` |
| `DATA_DIR` | Variable | Storage path; default `/data/visits` |
| `HASH_SALT` | Secret | Salt used to hash browser visitor IDs |
| `GEOIP_DB_PATH` | Variable | Path to a MaxMind GeoLite2 City database; default `/data/GeoLite2-City.mmdb` |
The top-level `app.py` starts the mounted Gradio/FastAPI application on port `7860`,
the standard port for Gradio Spaces. Do not configure a `PORT` variable for this Space;
that generic variable may be used by another process in the runtime.
## 2. Add tracking to another Space
### Static HTML or a custom frontend
Add this before `</body>`:
```html
<script
src="https://YOUR-ANALYTICS-SPACE.hf.space/tracker.js"
data-endpoint="https://YOUR-ANALYTICS-SPACE.hf.space/track"
data-space="YOUR_USERNAME/YOUR_SPACE"
data-key="YOUR_TRACKING_KEY"
defer>
</script>
```
Omit `data-key` when `TRACKING_KEY` is not configured.
### Another Gradio Space
See [`examples/gradio_example.py`](examples/gradio_example.py). It injects the same tracker through `gr.Blocks(head=...)`.
### Direct JavaScript
```javascript
fetch("https://YOUR-ANALYTICS-SPACE.hf.space/track", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Tracking-Key": "YOUR_TRACKING_KEY"
},
body: JSON.stringify({
space: "YOUR_USERNAME/YOUR_SPACE",
path: location.pathname,
referrer: document.referrer || null,
visitor_id: localStorage.getItem("hf_analytics_visitor")
}),
keepalive: true
});
```
## 3. Read statistics
Open the analytics Space to use the Gradio dashboard, or call the API directly:
```bash
curl "https://YOUR-ANALYTICS-SPACE.hf.space/stats?days=30"
```
With an admin key:
```bash
curl -H "X-Admin-Key: YOUR_ADMIN_KEY" \
"https://YOUR-ANALYTICS-SPACE.hf.space/stats?days=30"
```
## Storage
The default layout is:
```text
/data/visits/
β”œβ”€β”€ 2026-08-06.jsonl
β”œβ”€β”€ 2026-08-07.jsonl
└── ...
```
Without a bucket mounted at `/data`, files are written to the Space filesystem and may disappear after a restart or rebuild.
### IP-based location
To store approximate IP-based location, provide a licensed MaxMind GeoLite2
City database at `GEOIP_DB_PATH` (the default is
`/data/GeoLite2-City.mmdb`). Each event stores only the available coarse fields
under `location`: country code, country, region, and city. The raw IP is never
stored. If the database is absent or cannot identify an address, `location` is
`null` and tracking continues normally.
## Privacy and security
- A salted hash of the connecting IP address is stored as `ip_hash`; raw IP addresses are not stored.
- Approximate IP-based location is stored only when a GeoLite2 database is configured.
- The recorded address may be the Hugging Face proxy address rather than the visitor's original IP.
- The tracker stores the browser-reported timezone and language as coarse location hints; it does not collect GPS coordinates.
- Browser visitor IDs are salted and hashed before storage.
- Paths and referrers may contain sensitive information; omit them when unnecessary.
- `TRACKING_KEY` is visible to visitors when included in browser JavaScript. Treat it only as a low-value anti-spam key, never as a Hugging Face access token.
- Set an `ADMIN_KEY` before exposing raw events or private analytics.
- Publish an appropriate privacy notice for your users and jurisdiction.
## Local development
```bash
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
DATA_DIR=./local-data python app.py
```
Then open `http://localhost:7860`.
Run tests:
```bash
pip install -r requirements-dev.txt
pytest
```