Analytics without surveillance: explicit consent, layered gates, and never sending Class A data
Source: Dev.to
Overview
Analytics in health‑adjacent apps has a special failure mode: you add “just one metric”, then another, then a refactor starts sending richer context, and suddenly you’re collecting things you never intended to collect.
If you want privacy‑first, offline health tech to exist without surveillance, fund it by sponsoring the build: .
Pain Tracker avoids that drift with a few simple rules:
- Analytics is off by default (explicit consent).
- Defense‑in‑depth gating (multiple checks).
- Never include Class A health content (no notes, no symptoms, no meds).
The post is grounded in the repository’s implementation:
src/analytics/analytics-gate.tssrc/analytics/analytics-loader.tssrc/analytics/ga4-events.tssrc/components/AnalyticsConsentPrompt.tsxsrc/components/settings/PrivacySettings.tsxsrc/utils/usage-tracking.ts
Deployment‑Level Gate
Analytics is controlled with a Vite environment variable (e.g. VITE_ENABLE_ANALYTICS). When disabled, the app behaves as if analytics does not exist.
Why it matters
- Privacy‑friendly deployments can hard‑disable analytics.
- Prevents “whoops, we accidentally shipped tracking” moments.
User Consent
Even if analytics is enabled for a deployment, it does not run without user opt‑in. Pain Tracker includes a dedicated consent surface (prompt + settings) designed for trauma‑informed UX:
- Control is part of safety.
- “No” must be respected without nagging.
- “Change my mind later” must be possible.
Layered Checks
Analytics can accidentally turn on in several ways:
- A component calls a tracking helper on mount.
- A shared hook starts emitting events.
- A remote analytics script partially loads.
The repository mitigates this with layered checks:
- Env‑gate and consent‑gate decide if analytics should be enabled.
- The loader injects remote analytics only when allowed.
- Event senders verify the runtime is actually present before sending (no
gtag, no event).
This ensures that “disabled means no‑op” remains true.
Class A Data Protection
If your app stores Class A data (pain entries, symptoms, meds, free‑text notes), assume it will leak unless you deliberately design against it.
Pain Tracker’s event helpers aim to send only coarse information:
- Counts
- Booleans
- Category/bucket values
They do not send:
- Free text
- Per‑entry timestamps
- Anything that can reconstruct a user’s log
This is a pragmatic engineering rule, not a compliance claim: analytics should be useful without being invasive.
Local Usage Tracking
The repo also includes local usage‑tracking utilities (stored on‑device) intended for lightweight UX behavior and product insight without shipping data off‑device.
Guidelines
- Sanitize metadata.
- Do not store raw notes.
- Do not store enough detail to recreate someone’s history.
Local‑only tracking can still cover useful scenarios:
- “Has the user seen this onboarding tip?”
- “How often is export used?” (as a count, not content)
Quality Gates
Part 9 of the series introduces tests and quality gates that keep privacy promises from drifting over time. These gates enforce the rules described above throughout the codebase.
Sponsorship & Community
- Primary sponsor:
- Star the repository: