Analytics and privacy
How Nimriz logs click data, what privacy mode changes, and how realtime differs from reporting.
Analytics and privacy
Nimriz separates raw redirect event ingestion from dashboard reporting, and it defaults to a privacy-preserving capture mode.
Data flow
- Redirects emit raw click events to Cloudflare Analytics Engine.
- Scheduled jobs aggregate those events into Postgres rollups and counters.
- Stable reporting should use rollups. Realtime views should use live event queries.
Storage split
- Raw click events: Cloudflare Analytics Engine
- Operational records and rollups: Supabase Postgres
This split keeps redirect-path logging fast while still giving dashboards a stable reporting source.
Privacy mode
Privacy mode defaults to on for new accounts.
When privacy mode is on:
- raw IP addresses are not stored
- full user-agent strings are not stored
- event payloads omit IP and user-agent hashes
When privacy mode is off:
- IP and user-agent are hashed at the edge before storage
- hashes rotate daily
- raw identifier values are still never persisted
Best-effort dimensions
These fields are useful for reporting, but they are not guaranteed:
country,region,city,colodevice_categorybrowser_familyos_familyreferrerreferrer_hostsocial_sourcebot_flag
Build your UI and downstream logic to handle null or missing values gracefully.
GET /api/live-view
Returns recent raw-ish events from Analytics Engine for internal dashboards and debugging flows.
Query parameters
domain_id: optionalurl_id: optionallimit: optional
Response shape
{
"source": "analytics_engine",
"count": 2,
"events": [
{
"clicked_at": "2026-03-08T12:34:56.000Z",
"url_id": "22222222-2222-2222-2222-222222222222",
"domain_id": "11111111-1111-1111-1111-111111111111",
"short_code": "spring-launch",
"country": "US",
"device_category": "mobile",
"bot_flag": false,
"referrer_host": "twitter.com",
"social_source": "twitter",
"destination_url_capped": "https://example.com/landing"
}
]
}
GET /api/link-breakdowns
Returns per-link top-N analytics breakdowns from Analytics Engine.
Query parameters
url_id: requiredrange_days: optional, default30, max365include_bots: optional, defaultfalselimit: optional, default5, max20
Response shape
{
"ok": true,
"source": "analytics_engine",
"url_id": "22222222-2222-2222-2222-222222222222",
"range_days": 30,
"include_bots": false,
"limit": 5,
"sampled_counts": true,
"dimensions": {
"country": [
{ "label": "US", "clicks": 120 }
],
"device": [
{ "label": "Mobile", "clicks": 95 }
]
}
}
Realtime versus reporting
Use realtime when you need:
- recent traffic debugging
- rapid validation after a campaign launch
- confirmation that redirects are still logging
Use reporting rollups when you need:
- stable charts
- exports
- longer time ranges
- customer-visible analytics summaries
The same link can show recent traffic in live tools before that traffic appears in rollup-backed reports.
Bot handling
Bot traffic is flagged so dashboards can filter it. Not all bots are abusive. Common sources include preview crawlers, scanners, and automated checks.
Integration guidance
- Use
url_idas the stable identifier in downstream systems. - Treat missing referrers as normal, not as a bug by default.
- Do not assume live-view and rollup totals will match at the same moment.