|
Download README.md from nanye/analytics: direct link, hf CLI and curl.
- Browser
- Download file 5 kB
-
https://huggingface.co/spaces/nanye/analytics/resolve/main/README.md
- Command line
-
hf download hf://spaces/nanye/analytics/README.md
-
curl -L -o README.md https://huggingface.co/spaces/nanye/analytics/resolve/main/README.md
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 | |
| ``` | |