Skip to content

RevenueCat First-Feature-Used Audit Runbook

Owner: Subscription / iOS engineering Cadence: Run BEFORE removing any existing Pro gate. Re-run quarterly. Risk addressed: Premortem #3 — "Subscription MRR drops 40% after removing My Protocol paywall." Plan §D14 / pricing-revenuecat-audit todo.

Why we run this

Before removing the legacy My Protocol paywall (and the cycleSync / Performance / Fertility mode pills), we MUST know which gated features actually drive subscription conversions. If My Protocol is the dominant conversion driver, we need an equivalent or stronger gate replacement live in production for at least one full release cycle BEFORE we drop the old gate. Otherwise MRR collapses on the cutover.

This runbook produces a single answer:

Which feature-gated surfaces are responsible for each Pro conversion in the last 90 days?

…and it does so in a way an outside engineer can repeat 90 days from now.

Inputs you need

  • RevenueCat dashboard access (Onset project)
  • Read access to the subscription_events Supabase table OR exported RevenueCat events (CSV)
  • iOS analytics (ProductAnalytics.track events) for the same window — specifically paywall_shown events with the source property and pro_gate_blocked events with feature property

Steps

1. Pull last-90-day Pro conversions

In RevenueCat dashboard: - Filter Customers → Active subscribers → "started in last 90 days" - Export CSV with columns: customer_id, started_at, product_id, original_app_user_id

Or query via API if available:

GET /v2/projects/{onset}/subscriptions
  ?starts_after={ISO 90 days ago}
  &per_page=200

2. Join with paywall-trigger analytics

For each customer in step 1, find the paywall_shown event closest in time BEFORE their subscription_started event (within 7 days). The source property on that event tells us which feature-gated surface triggered the purchase. Surfaces logged today include:

  • onboarding_step_6 — the hard onboarding paywall
  • my_protocol_unlock — the legacy My Protocol gate (the one we are considering removing)
  • bottle_scan_limit — the 3-free-scans-per-month gate
  • protocol_item_cap — the 10-item self-built cap
  • labs_intelligence_unlock — Labs Intelligence (Pro perk)
  • ai_insights_unlock — AI insights (Pro perk; gated by FeatureFlags)
  • protocol_lab_unlock — Protocol Lab simulations (Pro perk)
  • multi_protocol_unlock — Multiple custom protocols (Pro perk)
  • cloud_sync — Backup & multi-device sync of self-built data (Pro perk). Triggered when a Free user presses "Sync this device" in Settings or sees the "Backup & sync — PRO" row. Practitioner data syncs separately and stays free, so this gate only fires for users who have built their own routine and want it backed up. Expect most signal here from reinstall / new-device scenarios. New as of the 2026-05 freemium rework.

If paywall_shown.source is missing from older events, fall back to the last pro_gate_blocked.feature event in the same window.

3. Aggregate and rank

Group conversions by source. Compute:

| source | conversions (n) | % of total | 90-day retention |

Rank by % of total. The top 1–3 sources are the conversion drivers.

4. Decision rule

  • If my_protocol_unlock is <= 20% of conversions → safe to remove the My Protocol paywall in the next release once Intelligence Bundle gates are live.
  • If my_protocol_unlock is 20–40% of conversions → ship Intelligence Bundle gates first, observe one release cycle, then re-run this audit before removing.
  • If my_protocol_unlock is > 40% of conversions → DO NOT REMOVE. Find a stronger replacement gate before any cutover.

5. Document the result

Paste the result table here on each run, with a date and the engineer who ran it. Keep at least the last 4 runs visible.

History

Date Engineer Top driver My Protocol % cloud_sync % Decision
TBD TBD TBD TBD TBD TBD
  • Onset/Core/App/FeatureGate.swift — the new gate API (Intelligence Bundle hooks)
  • Onset/Core/App/ProGateStrategy.swift — legacy gate API kept for backward compat
  • Onset/Core/Subscriptions/SubscriptionManager.swift — RevenueCat client. entitlementIdentifier = "pro"
  • clinic-protocol-end-to-end_a9f4d416.plan.md — the plan that motivates this audit