The conversion paradox
Android's subscription performance looks like a platform limitation until you separate the funnel into two stages. Download to paid conversion at day 35 sits at 0.9% on Android versus 2.6% on iOS โ a threefold gap that suggests fundamental behavioral differences between the platforms. Trial to paid conversion tells a different story: 32.5% on Android, 32.6% on iOS. Statistically identical.
Once a user starts a trial on either platform, they convert at the same rate. The gap exists because Android apps send far fewer users into that first stage. The problem is not the trial experience, the product, or the audience. The problem is funnel entrance.
89.4% of all trial starts happen on install day. Users who download with intent act immediately. Users who do not start a trial during the first session rarely return to initiate one later. That makes the first paywall impression the moment that determines most subscription revenue on Android. Everything downstream โ onboarding, trial experience, product engagement โ performs as well as iOS. The question is whether users reach that moment at all.
Where the funnel breaks
Two variables control whether a user is presented with a trial: what you show (paywall type) and when you show it (timing). Both are controllable.
Paywall model drives a fivefold difference
Hard paywalls โ where users must engage with a subscription offer before accessing core features โ achieve 10.7% median day-35 conversion. The top 10% reach 38.7%. Freemium models convert at 2.1% median. The retention difference is negligible: hard paywalls retain 27% of subscribers at 12 months, freemium retains 28%.
For most categories, the hard paywall advantage is structural. If your product delivers clear value in a single session, a hard paywall is the correct model. Freemium remains appropriate for products with network effects or long value-discovery cycles โ social apps, community tools โ where acquiring a broad user base precedes monetization. One case where freemium shows delayed strength: at week six, freemium apps convert 22.9% of their cohort versus 15.3% for hard paywalls. If your product's value builds gradually over weeks, freemium captures users a hard paywall would lose.
Timing is binary
The 89.4% Day 0 trial start rate has a direct implication: show your paywall in the first session. Every session after install is a sharply diminishing return. This does not mean presenting the paywall before onboarding. The pattern that works is: deliver one compelling value moment โ a completed task, a feature reveal, a concrete output โ then present the paywall. On Day 0.
The silent failure: offer misconfiguration
Even with correct paywall type and timing, a trial can fail to surface due to Google Play's subscription billing offer structure. This is a configuration issue, and it produces no visible error.
Every Google Play subscription consists of a base plan and optional promotional offers. An offer defines pricing phases (free trial, introductory price, or both) that precede the base plan price. Each offer has offer tags โ strings you assign in the Play Console โ and an offer token used to initiate purchase.
When RevenueCat fetches products, each Google Play offer becomes a GoogleSubscriptionOption. The SDK groups these into a SubscriptionOptions collection and exposes a defaultOffer property โ the option your paywall displays unless you explicitly select another.
The selection algorithm:
- Filter out offers tagged
rc-ignore-offerorrc-customer-center - Select the offer with the longest free trial
- If no trial exists, select the offer with the lowest introductory price
- If no promotional offers pass, fall back to the base plan with no trial
rc-ignore-offer, attached to the wrong base plan, or missing offer tags entirely, defaultOffer returns the base plan. Your paywall renders. No error appears. The trial is gone.
Detection
Before optimizing anything else, verify that defaultOffer resolves to an offer with a free trial. Check the freePhase property:
val offering = Purchases.sharedInstance.getOfferings().current val product = offering?.availablePackages?.first()?.product val hasFreeTrialOption = product?.defaultOption?.freePhase != null
A null freePhase means no promotional phase will be shown. Inspect your Play Console offer configuration. Confirm the offer is active, attached to the correct base plan, and not tagged for exclusion.
Trial length matters
Apps offering longer trials show roughly 17 percentage points higher trial-to-paid conversion. This is correlation: apps that offer longer trials tend to be productivity and creative tools where extended trials reflect deliberate product strategy. Yet 55% of all trials are now four days or shorter, up from 42% the previous year. Only 5% offer 17 days or more.
For apps where value compounds over time, a four-day trial may end before a user has a meaningful product experience. A 14 or 30-day trial gives the product enough time to demonstrate value. If your trial-to-paid rate is below the 32.5% Android median, trial length is a high-leverage variable to test.
The platform asymmetry
One structural difference shapes conversion patterns: iOS sends a system-level push notification before a trial ends, reminding the user it will convert to paid. Google Play does not send an equivalent notification. On iOS, this is a built-in re-engagement nudge at the critical conversion moment. On Android, that reminder is entirely your responsibility โ an in-app banner, a backend-triggered push, or a re-engagement flow when the user returns near trial end.
This platform assist partially explains why trial-to-paid rates look similar despite very different trial-starter pool sizes. If your Android trial-to-paid rate is below your iOS rate, the absence of a trial-end reminder in your app is a likely contributor.
Measurement and iteration
All of these variables โ paywall type, timing, trial length, offer selection โ interact in ways that are difficult to reason about without measurement. RevenueCat Experiments enables A/B tests against these variables without code changes. Create a variant offering with different configuration (trial length, default offer, package lineup). The system randomly assigns users to control or variant, tracks behavior through the full trial and conversion cycle, and surfaces day-35 conversion, LTV, and trial start rate by variant.
Attach a placement identifier to every paywall using PresentedOfferingContext:
This context travels with the transaction and appears in your dashboard and webhook events. Compare trial start rates and conversion across placements โ "onboarding_paywall", "settings_upgrade", "feature_gate" โ to determine which surface is worth optimizing first.
The path forward
The Android conversion gap is primarily a funnel-entrance problem with identifiable causes. The threefold difference in download-to-paid between Android and iOS does not reflect a platform ceiling. It reflects the aggregate effect of wiki:conversion-rate-optimization-cro failures: offer misconfiguration, freemium models that suppress trial uptake, paywalls shown too late or not at all, and the absence of platform-level trial reminders.
The sequence:
- Confirm
defaultOfferresolves to an option with a non-nullfreePhase. If not, fix Play Console configuration before changing anything else. - If running freemium, test a hard paywall variant and measure both trial start rate and 12-month wiki:retention-rate.
- If already running a hard paywall, test a longer trial duration.
- Add
placementIdentifierto paywall surfaces so you can attribute trial starts to specific moments.