Generated file. Source:
docs/telemetry_worker.mdEdit the source document and runnpm run docs:syncto refresh this published copy.
Telemetry Worker¶
Goal¶
This worker collects only ten anonymous technical events:
password_gate_unlockedpage_view_calculatorpage_view_how_it_workspage_view_product_roadmapclick_how_it_works_navclick_product_roadmap_navclick_technical_documentationcalculator_inputs_changedresults_renderedyearly_analysis_mode_changed
It is designed to be:
- removable
- cookie-free
- free of user identifiers
- free of form data
- limited to simple event counts, last-seen timestamps, and a short rolling history of recent events
Does the app have to be hosted on Cloudflare?¶
No.
Only the worker needs to be deployed to Cloudflare.
The frontend can still be deployed anywhere else or hosted on a completely different provider.
For this project, telemetry is intentionally disabled on local localhost and 127.0.0.1, so local development sessions do not send metrics to the worker.
What matters is:
- the Worker must be publicly reachable
- the Worker must allow the frontend origin in CORS
- the frontend must use the Worker URL as
VITE_TELEMETRY_ENDPOINT
Important:
- the allowed origin must match the browser URL exactly
- local
localhost/127.0.0.1development is no longer a telemetry sender in this project - after changing
ALLOWED_ORIGINS, you must redeploy the Worker
What the worker stores¶
The worker stores only:
- total event counters
- per-event counters
- last seen timestamp per event
- a rolling buffer of the most recent events with timestamps
Implementation note:
yearly_analysis_mode_changedis emitted by the shared global analysis-mode interactions exposed in the chart and detailed yearly-table sections
It does not need cookies, local storage, or a user identifier.
Current implementation notes:
- the frontend sends telemetry with a regular
fetch - the frontend does not use cookies for telemetry
- the Worker accepts only a fixed allowlist of event names
- the recent event buffer currently stores up to
200events total
Endpoints¶
POST /events¶
Accepts a payload like:
{
"event": "page_view_calculator",
"ts": "2026-03-23T12:34:56.000Z"
}
Allowed events are hardcoded in the worker.
GET /stats¶
Returns counters and last seen timestamps.
This endpoint requires the request header:
x-telemetry-token: your-secret-token
GET /events¶
Returns the most recent stored events.
Optional query param:
?limit=20
Maximum stored history is currently 200 events.
The limit query parameter controls only how many of the already stored events are returned in the response.
Examples:
?limit=20-> return up to 20 newest events?limit=100-> return up to 100 newest events?limit=200-> return up to the full stored buffer
This does not change how many events the Worker stores internally.
This endpoint also requires:
x-telemetry-token: your-secret-token
POST /reset¶
Resets:
- all counters
- all
lastSeenvalues - the recent event history
This endpoint also requires:
x-telemetry-token: your-secret-token
GET /health¶
Simple health check.
Files¶
- Worker code:
index.ts: cloudflare/telemetry-worker/src/index.ts - Worker config:
wrangler.toml: cloudflare/telemetry-worker/wrangler.toml
Setup Step by Step¶
1. Install Wrangler¶
If you do not have it yet:
npm install -g wrangler
or use npx wrangler.
2. Login to Cloudflare¶
wrangler login
3. Create a KV namespace¶
Run:
wrangler kv namespace create TELEMETRY_KV
wrangler kv namespace create TELEMETRY_KV --preview
Copy the returned IDs into:
idpreview_id
inside wrangler.toml: cloudflare/telemetry-worker/wrangler.toml
4. Configure allowed origins¶
In wrangler.toml: cloudflare/telemetry-worker/wrangler.toml, set:
ALLOWED_ORIGINS = "https://bondprofitabilitycalculator.niwciu.workers.dev"
Use a comma-separated list.
For the current deployed app, add:
https://bondprofitabilitycalculator.niwciu.workers.dev
5. Configure a token for reading stats¶
Set a Worker secret:
wrangler secret put STATS_READ_TOKEN
Enter a long random token.
This token is only for reading /stats.
It is not used by the frontend.
6. Run the worker locally¶
From the repo root:
wrangler dev --config cloudflare/telemetry-worker/wrangler.toml
You should get a local Worker URL.
7. Point the frontend to the worker¶
In the frontend environment used by the deployed app:
VITE_ENABLE_TELEMETRY=true
VITE_TELEMETRY_ENDPOINT=https://bond-calculator-telemetry.niwciu.workers.dev/events
Local localhost / 127.0.0.1 sessions are blocked in the frontend telemetry layer, so keeping this variable in local env no longer makes the browser send metrics during development.
8. Deploy the worker¶
wrangler deploy --config cloudflare/telemetry-worker/wrangler.toml
After deploy, use the returned workers.dev URL in the frontend env.
Important:
- redeploy is required not only after changing
ALLOWED_ORIGINS - redeploy is also required after any change to Worker code or
wrangler.toml - restarting Vite is required after changing frontend env values
How to read stats¶
Example:
curl -H "x-telemetry-token: YOUR_SECRET_TOKEN" \
https://bond-calculator-telemetry.niwciu.workers.dev/stats
You can also use the lightweight helper script from the repo root:
python3 scripts/telemetry_cli.py stats --token YOUR_SECRET_TOKEN
or with an environment variable:
export TELEMETRY_TOKEN=YOUR_SECRET_TOKEN
python3 scripts/telemetry_cli.py stats
How to read recent events / logs¶
Example with curl:
curl -H "x-telemetry-token: YOUR_SECRET_TOKEN" \
"https://bond-calculator-telemetry.niwciu.workers.dev/events?limit=20"
Example with the helper script:
python3 scripts/telemetry_cli.py events --token YOUR_SECRET_TOKEN --limit 20
This prints a compact log-like view:
2026-03-23 19:12:01+00:00 page_view_calculator
2026-03-23 19:12:04+00:00 page_view_how_it_works
Useful variants:
python3 scripts/telemetry_cli.py event-types
python3 scripts/telemetry_cli.py health
python3 scripts/telemetry_cli.py stats --json --token YOUR_SECRET_TOKEN
python3 scripts/telemetry_cli.py events --json --token YOUR_SECRET_TOKEN --limit 100
python3 scripts/telemetry_cli.py reset --token YOUR_SECRET_TOKEN
If Cloudflare returns Error 1010: Access denied for the Python script, it usually means the default script signature was blocked. The helper now sends its own User-Agent, and you can override it if needed:
python3 scripts/telemetry_cli.py stats --token YOUR_SECRET_TOKEN \
--user-agent "BondTelemetryCLI/1.0"
Example response:
{
"totalEvents": 12,
"lastEventAt": "2026-03-23T12:34:56.000Z",
"stats": [
{
"event": "password_gate_unlocked",
"count": 2,
"lastSeen": "2026-03-23T10:10:10.000Z"
},
{
"event": "page_view_calculator",
"count": 6,
"lastSeen": "2026-03-23T12:00:00.000Z"
}
]
}
How to read recent events¶
Example:
curl -H "x-telemetry-token: YOUR_SECRET_TOKEN" \
"https://bond-calculator-telemetry.niwciu.workers.dev/events?limit=20"
Example response:
{
"totalStored": 12,
"limit": 20,
"events": [
{
"event": "page_view_product_roadmap",
"ts": "2026-03-23T12:34:56.000Z",
"recordedAt": "2026-03-23T12:34:56.321Z"
},
{
"event": "password_gate_unlocked",
"ts": "2026-03-23T12:30:00.000Z",
"recordedAt": "2026-03-23T12:30:00.111Z"
}
]
}
Notes:
tsis the timestamp sent by the frontendrecordedAtis when the Worker stored the event
How to reset telemetry¶
Example:
curl -X POST \
-H "x-telemetry-token: YOUR_SECRET_TOKEN" \
https://bond-calculator-telemetry.niwciu.workers.dev/reset
Troubleshooting¶
If stats stay at zero:
- confirm the frontend is open under an origin allowed by the Worker
- confirm
.env.localcontains:
VITE_ENABLE_TELEMETRY=true
VITE_TELEMETRY_ENDPOINT=https://bond-calculator-telemetry.niwciu.workers.dev/events
- restart Vite after env changes
- redeploy the Worker after any Worker-side config or code change
- in browser DevTools -> Network, check the request to
/events
Typical signals:
202-> event accepted by the Worker403-> origin not allowed404-> wrong endpoint URL- no request at all -> frontend telemetry is not firing or env is not active
Example response:
{
"ok": true,
"reset": true
}
Privacy Notes¶
Recommended operating rules:
- do not add cookies
- do not add user IDs
- do not add IP-based analysis in your own reporting layer
- do not send form inputs
- do not expand the event catalog without a clear reason
This keeps the telemetry minimal and easier to justify as a lightweight operational signal.