File size: 4,999 Bytes
aa7e587 9ecb1ae aa7e587 9ecb1ae aa7e587 9ecb1ae aa7e587 9ecb1ae aa7e587 9ecb1ae aa7e587 9ecb1ae a10ad9b 9ecb1ae a10ad9b 9ecb1ae a10ad9b 9ecb1ae | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | ---
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
```
|