Tracing sensitive health data from a period-tracking app, through third-party analytics SDKs, into advertiser data pipelines
Most consumer health apps are not built by companies with in-house analytics infrastructure. Instead, developers drop in free SDKs — the Facebook (Meta) SDK for app events, Google Firebase Analytics, AppsFlyer, Branch, Mixpanel — to get crash reporting, retention funnels, and ad-attribution "for free." Each SDK runs with the same permissions as the host app and can transmit data the moment the process starts, often before any privacy policy is shown.
A typical period- or mood-tracking app integrates its core UI plus a stack of third-party libraries: Facebook SDK for Android/iOS (App Events, Audience Network), Firebase/Google Analytics, an attribution SDK (AppsFlyer or Branch) to measure which ad campaign drove the install, and a crash reporter (Crashlytics, Sentry). Each of these ships as a compiled binary the app developer rarely audits line-by-line.
The Facebook SDK in particular auto-logs "standard events" — app install, app open, session duration — as soon as it initializes, using the exact same code path used for custom events the developer defines. If a developer names a custom event log_period_start or passes a free-text parameter like symptom_notes into an analytics call meant for UI debugging, that string is serialized into the same outbound JSON payload as generic engagement telemetry, with no built-in filter distinguishing "screen tapped" from "date of last menstrual period."
This is the structural root cause: SDKs do not know what is sensitive. They forward whatever key-value pairs the host app hands them to a fixed collection endpoint, and the collection endpoint belongs to an advertising company whose business model is built on aggregating exactly this kind of behavioral signal across millions of apps.
A 2019 Privacy International investigation of period-tracking apps found that Flo, Maya, and MIA Fem transmitted data to Facebook's Graph API via the App Events SDK the moment the app was opened — before the user had seen or accepted any privacy policy, and irrespective of whether the user even had a Facebook account.
Analytics SDKs are designed to be schema-flexible: a call like logEvent("answered_question", {question: "Have you had thoughts of self-harm?", answer: "Yes"}) is syntactically identical, from the SDK's point of view, to logEvent("button_clicked", {button_id: "next_page"}). Both are just a string event name plus a dictionary of parameters, and both get the same treatment: batched locally, then POSTed as JSON to the vendor's collection domain (graph.facebook.com/app_events, google-analytics.com/g/collect, api2.branch.io) alongside a persistent device identifier.
Common identifier types attached to every event regardless of content:
• Advertising ID (IDFA on iOS, GAID on Android) — a resettable but highly persistent cross-app identifier • Device fingerprint components — OS version, screen resolution, carrier, locale, timezone • Hashed or plaintext email/phone if the app has a login system (Facebook SDK's Advanced Matching feature explicitly hashes and forwards these for ad matching) • IP address, captured server-side at the collection endpoint regardless of what the client sends
Because the advertising ID is stable across sessions and often linkable to a real identity through other apps on the same device, a single leaked event containing a health-related string is enough to associate a real person with a specific sensitive attribute — a mental-health screening answer, a fertility status, a symptom entry — inside an ad-tech identity graph.
To prove what an app actually sends — as opposed to what its privacy policy claims — researchers and auditors intercept the device's live network traffic. Because virtually all mobile telemetry now travels over TLS, this requires positioning a trusted proxy between the app and the internet and, when the app pins its certificates, defeating that pinning at runtime.
A standard SDK data-leakage audit follows a repeatable pipeline used by academic researchers (e.g. the AppCensus and Exodus Privacy projects) and regulatory investigators alike:
1. Install a proxy CA certificate as a trusted root on the test device (or a rooted/jailbroken emulator), and route all device traffic through mitmproxy or Charles Proxy running on a controlling workstation.
2. If the app uses certificate pinning (validating the server's certificate against a hardcoded fingerprint rather than the OS trust store — common in security-conscious health apps), attach Frida at runtime and hook the platform TLS validation calls (e.g. SSLContext, OkHttp's CertificatePinner on Android, or NSURLSession delegate methods on iOS) to force acceptance of the proxy's certificate. Objection provides prebuilt bypass scripts for this exact purpose.
3. Exercise the app through a realistic session: create an account, log symptoms, complete an onboarding mental-health screener, set a period start date — mirroring what a real user does in their first ten minutes.
4. Export the captured HTTP Archive (HAR) log and filter requests by destination domain, isolating calls to known third-party collection endpoints rather than the app's own first-party backend.
Static analysis complements this dynamic capture: tools like MobSF and the Exodus Privacy database decompile the APK/IPA and enumerate every embedded tracker SDK by matching known package signatures, giving an inventory even before a single network packet is captured.
Because TLS encrypts the payload, not the destination, even a passive DNS-level observer can already see that a health app is talking to graph.facebook.com or googleadservices.com. Full MITM interception is what is required to see exactly which fields are inside that encrypted call.
Regulatory complaints against health apps rely heavily on this exact interception methodology because it converts a policy dispute ("did the privacy policy promise not to share data?") into a factual, reproducible technical finding ("this specific HTTP POST to this specific domain contained this specific field"). The FTC's 2021 complaint against Flo Health and its 2023 complaint against BetterHelp both cite network traffic analysis showing sensitive fields — including responses to intake mental-health questionnaires in the BetterHelp case — transmitted to Facebook, Snapchat, Pinterest, and Criteo via their respective SDKs.
Because the SDK, not the app's own server, initiates these calls directly from the device, the traffic is visible without needing any cooperation or subpoena against the company's backend — a captured HAR file from a single test device is sufficient to demonstrate the disclosure pattern, which is why this technique has become the default first step in health-app privacy investigations by both journalists (The Wall Street Journal's 2019 Flo investigation) and regulators.
Once raw HTTPS payloads are decrypted, the audit becomes a string-matching and schema-mapping exercise: every JSON key and value inside each outbound request is checked against a dictionary of sensitive field names and value patterns, then cross-referenced against the app's own privacy policy to identify undisclosed disclosures.
A captured POST to graph.facebook.com/app_events from a real menstrual-tracking app audit typically contains a JSON array of event objects, each with a _eventName field and a custom_events blob. Illustrative (redacted/reconstructed) shape:
{ "event": "CustomEvent", "_eventName": "fa_cycle_logged", "_valueToSum": 1, "cycle_day": 14, "last_period_start": "2026-07-29", "symptom_tags": "cramping,fatigue,anxiety", "advertising_id": "38400000-8cf0-...", "extinfo": ["a2","com.app.id","1.0",...] }
A payload detector runs three layers of matching against every field:
1. Key-name dictionary — flags keys like period, cycle, pregnan*, mood, symptom, diagnosis, medication, answer_*, screener_* regardless of value 2. Value-pattern regex — flags values matching date-of-birth patterns, ICD-10-like codes, free-text answers longer than a threshold containing clinical vocabulary 3. Cross-reference against declared purpose — a field can be technically "just a string" to the SDK but still count as Protected Health Information in context, because HIPAA's and the FTC's definitions turn on whether the data relates to an individual's health condition, not on the data type alone
The "PII Detection Sensitivity" slider in this simulation controls exactly this threshold: low sensitivity only flags obvious key names (period_date), while high sensitivity also flags contextual free-text fields (symptom_tags, screener_answer) that a naive scanner would treat as harmless strings.
In its 2023 complaint, the FTC found BetterHelp shared consumers' email addresses, IP addresses, and answers to a clinical intake questionnaire — including whether the person had previously attempted suicide — with Facebook via the standard "CompleteRegistration" and custom event parameters, despite explicit promises that health information "will not be shared" with advertisers.
A common misconception is that any app handling health data is automatically covered by HIPAA. In reality, HIPAA's Privacy Rule only binds "covered entities" (health plans, healthcare clearinghouses, and healthcare providers that transmit claims electronically) and their "business associates." A direct-to-consumer wellness app like a period tracker, mood journal, or DTC therapy-matching service is, in almost all cases, none of these — it collects data directly from the consumer, not from a covered provider relationship, so HIPAA simply does not attach.
This regulatory gap is precisely what the FTC has stepped in to fill using two tools:
• Section 5 of the FTC Act (unfair or deceptive practices) — used when an app's actual data-sharing contradicts its stated privacy promises, as in Flo, BetterHelp, and GoodRx • The Health Breach Notification Rule, 16 CFR Part 318 — originally written for PHR (personal health record) vendors, formally updated in April 2024 to make explicit that a "breach" includes any unauthorized disclosure of health data to a third party, such as sharing with an ad-tech SDK without consent, not just hacking incidents. The FTC applied this rule for the first time in the GoodRx case (February 2023, $1.5M penalty) and again against BetterHelp and the ovulation-tracking app Premom.
Between 2021 and 2023 the FTC brought a string of enforcement actions that, together, form the operative case law for SDK-based health data leakage. Each followed the same fact pattern uncovered by the interception-and-payload-forensics process described above: a privacy policy promising confidentiality, and captured network traffic showing sensitive fields flowing to Meta, Google, or ad-tech intermediaries.
Flo Health, maker of one of the most-downloaded period-tracking apps, promised users their health information "will not be shared" with third parties. The FTC alleged that Flo's Android app disclosed to Facebook, via the App Events SDK, when a user was menstruating or had indicated an intent to get pregnant — sent as custom app-event parameters immediately upon the user entering that data, regardless of whether the user had a Facebook account.
The resulting January 2021 consent order did not include a monetary fine (a first-of-its-kind action against this type of conduct), but required Flo to: notify all affected users of the disclosure, obtain an independent privacy audit for 20 years, and — critically — instruct every third party that received the improperly disclosed data (Facebook, Google, Flurry, AppsFlyer) to destroy it. This "instruct third parties to delete downstream data" remedy became a template for subsequent health-app cases.
BetterHelp, an online therapy-matching platform, settled with the FTC for $7.8 million in consumer refunds in July 2023. The complaint alleged BetterHelp used consumers' email addresses and health intake-questionnaire responses to build custom and lookalike advertising audiences on Facebook, and shared data with Snapchat, Pinterest, and Criteo — despite specific promises in its privacy policy and on its "Privacy" landing page that health information would be kept confidential.
GoodRx, a prescription discount and telehealth platform, agreed to pay $1.5 million in February 2023 in the FTC's first-ever enforcement action under the Health Breach Notification Rule. GoodRx had shared users' prescription drug names and health conditions with Facebook and Google Ads for years, using this data to target users with drug-specific advertising, while its privacy policy claimed it would not share such information. The order permanently barred GoodRx from sharing health data with advertisers for ad-targeting purposes.
Premom, an ovulation-tracking app, settled in 2023 (FTC + co-filed by the Illinois Attorney General under the Genetic Information Privacy Act theory) after sending users' pregnancy status and fertility data to AppsFlyer, Google, and two Chinese analytics firms.
A recurring evidentiary detail across all four cases: investigators did not need internal company documents to prove the violation. A single captured, decrypted HTTPS session from a test device — the same MITM technique described in Stage 2 — was sufficient to demonstrate exactly which fields left the device and where they went.
| Product | Indication | Trial Design | Key Result |
|---|---|---|---|
| Flo Health | Meta App Events SDK | Menstrual/pregnancy-intent flags sent as custom event params | Jan 2021 · consent order, third-party data destruction |
| BetterHelp | Meta, Snapchat, Pinterest, Criteo | Intake questionnaire answers + email used for ad audiences | Jul 2023 · $7.8M consumer refunds |
| GoodRx | Meta App Events, Google Ads | Prescription drug names and conditions used for ad targeting | Feb 2023 · $1.5M, first HBNR case |
| Premom | AppsFlyer, Google, CN analytics | Ovulation/pregnancy status shared without consent | 2023 · $100K, FTC Act + HBNR counts |
The fix that emerges from every one of these enforcement orders is architectural, not just a policy rewrite: sensitive fields must never reach a third-party SDK's network layer in the first place. This is achieved by sandboxing SDK data access, minimizing what is logged, and gating all third-party network egress behind explicit, verified consent.
1. Data minimization at the call site: strip or refuse to log any field matching a sensitive-field dictionary before it is ever handed to a third-party SDK's logEvent() call. This means never passing raw symptom text, screener answers, or calculated dates like "next period" directly into analytics parameters — only pre-aggregated, non-identifying signals (e.g. "screen_viewed: onboarding_step_3") should reach the SDK layer at all.
2. SDK network sandboxing: wrap third-party SDKs behind an internal proxy layer or a mediation library that intercepts every outbound call the SDK attempts, applies an allow-list of approved endpoints and an approved field schema, and blocks or redacts anything outside it — functionally the same MITM technique auditors use, but running permanently inside the app rather than only during a one-time test. Some mobile platforms now support this natively via network extension APIs and OS-level app sandboxing entitlements.
3. Consent-gated initialization: third-party SDKs are not initialized — meaning no network module loads, no auto-events fire — until the user has completed an explicit, granular opt-in for each data-sharing purpose (analytics vs. advertising vs. attribution), rather than the "SDK loads first, consent banner shown after" pattern that caused the Flo and BetterHelp violations. Apple's App Tracking Transparency (2021) and Google Play's Data Safety section (2022) both push toward this model by requiring disclosure of SDK data use before app review approval.
Apple's 2024 requirement that apps declare a "reason" for using any Required Reason API, combined with mandatory Privacy Manifests for third-party SDKs themselves, effectively forces SDK vendors like Meta and Google to publish machine-readable declarations of what data their code collects — turning what used to require a manual MITM audit into a static, auditable disclosure at build time.
Sandboxing is not a one-time fix — SDK vendors update their libraries frequently, and a routine SDK version bump can silently reintroduce auto-logged fields. Mature health-app teams now run the exact interception pipeline from Stage 2 continuously in CI/CD: every build is proxied through an automated mitmproxy harness, outbound requests are diffed against an approved-fields allow-list, and any new field or new destination domain fails the build.
Static scanning (MobSF, Exodus Privacy signatures) runs alongside dynamic interception to catch SDKs that only phone home under specific conditions (e.g. only after N days, or only for a subset of users in an A/B test) that a single manual test session might miss. Some organizations additionally commission independent third-party privacy audits — a remedy the FTC has now written directly into consent orders for Flo, BetterHelp, and GoodRx, typically requiring 10–20 years of recurring audits reported back to the agency.